[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-nvidia-earth2studio-create-prognostic":3,"mdc--18dra7-key":31,"related-repo-nvidia-earth2studio-create-prognostic":2295,"related-org-nvidia-earth2studio-create-prognostic":2399},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":20,"repoUrl":21,"updatedAt":22,"license":23,"forks":24,"topics":25,"repo":26,"sourceUrl":29,"mdContent":30},"earth2studio-create-prognostic","create Earth2Studio prognostic model wrappers","Create Earth2Studio prognostic (time-stepping forecast) model wrappers. Do NOT use for diagnostic models, data sources, or installation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},"nvidia","NVIDIA","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fnvidia.png",[12,16,17],{"name":13,"slug":14,"type":15},"Forecasting","forecasting","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"Simulation","simulation",2473,"https:\u002F\u002Fgithub.com\u002FNVIDIA\u002Fskills","2026-07-14T05:29:23.175426","Apache-2.0",281,[],{"repoUrl":21,"stars":20,"forks":24,"topics":27,"description":28},[],"AI agent skills published by NVIDIA","https:\u002F\u002Fgithub.com\u002FNVIDIA\u002Fskills\u002Ftree\u002FHEAD\u002Fskills\u002Fearth2studio-create-prognostic","---\nname: earth2studio-create-prognostic\nversion: 0.16.0\nlicense: Apache-2.0\nmetadata:\n  author: NVIDIA Earth-2 Team \u003Cagent-skills@nvidia.com>\n  tags: [earth2studio, prognostic-model, python]\ndescription: >\n  Create Earth2Studio prognostic (time-stepping forecast) model wrappers.\n  Do NOT use for diagnostic models, data sources, or installation.\nargument-hint: URL or local path to reference inference script (optional)\n---\n\n## Quick Start Checklist\n\n**Do these steps IN ORDER. Do not skip any step.**\n\n- [ ] Read this SKILL.md completely first\n- [ ] Get reference script (Step 0)\n- [ ] Create `earth2studio\u002Fmodels\u002Fpx\u002F\u003Cname>.py` with triple inheritance\n- [ ] Create `test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py` with mock tests\n- [ ] Run: `uv run pytest test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py -v`\n- [ ] Add\u002Fupdate model extra, install docs, API docs, and changelog (Steps 1-2, 9)\n- [ ] Run: `make format && make lint`\n\n> **⚠️ CRITICAL:** Always use `uv run` for Python commands:\n> - ✅ `uv run pytest ...` \u002F `uv run python ...`\n> - ❌ `pytest ...` \u002F `python ...` (missing dependencies)\n>\n> **Stuck or wrong output:** Do not keep retrying the same fix. Follow\n> [Self-Improvement](#self-improvement) to patch this skill before continuing.\n\n## Purpose\n\nImplement a prognostic model wrapper connecting third-party ML weather models\nto Earth2Studio. Prognostic models time-integrate forward—given initial state,\nthey predict future states by stepping through time (e.g., 6-hour increments).\n\n## Workspace\n\n| Context | Location |\n|---------|----------|\n| Harbor eval | Write to `\u002Fworkspace\u002Foutput\u002Fearth2studio\u002Fmodels\u002Fpx\u002F...` |\n| Harbor + `--copy-repo` | Full checkout at `\u002Fworkspace\u002Frepo` |\n| Local clone | Directory with `pyproject.toml` |\n\n**Never read `evals\u002Ftargets\u002F`** — grader references only.\n\n### Reference Files\n\nLoad on demand during the matching step:\n\n| File | Content | Load at |\n|------|---------|---------|\n| `references\u002Fskeleton-template.py` | Full model skeleton with FILL comments | Steps 3–6 |\n| `references\u002Fmethod-templates.py` | Canonical method implementations | Steps 4–6 |\n| `references\u002Ftesting-guide.py` | Test skeleton and mock patterns | Step 7 |\n| `references\u002Fvalidation-guide.md` | Comparison scripts, PR, code review | Steps 10–11 |\n\n---\n\n## Workflow Steps\n\n### Step 0 — Get Reference Script\n\nIf `$ARGUMENTS` provided, use it. Otherwise ask:\n> Please provide a reference inference script URL\u002Fpath.\n\n### Step 1 — Analyze & Propose Dependencies\n\nAnalyze: packages, architecture, I\u002FO shapes, time step, resolution, checkpoint.\n\nPropose `pyproject.toml` group (alphabetical, add to `all`). Every\nprognostic model must have an optional dependency extra, even when no packages\nare required:\n```toml\nmodel-name = [\"package1>=version\", \"package2\"]\n# or, when no additional packages are required:\nmodel-name = []\n```\n\n**[CONFIRM]** Present dependencies and ask user to approve.\n\n### Step 2 — Add Dependencies\n\nEdit `pyproject.toml`: add the model extra alphabetically, even if it is\nempty, and update the `all` aggregate.\n\n### Step 3 — Create Model File\n\n**File:** `earth2studio\u002Fmodels\u002Fpx\u002F\u003Clowercase>.py`\n\n**Required inheritance (all three):**\n```python\nclass ModelName(torch.nn.Module, AutoModelMixin, PrognosticMixin):\n```\n\n**Required imports:**\n```python\nimport numpy as np\nimport torch\nfrom earth2studio.models.auto import AutoModelMixin, Package\nfrom earth2studio.models.batch import batch_coords, batch_func\nfrom earth2studio.models.px.base import PrognosticMixin\nfrom earth2studio.models.utils import create_coords_from_lat_lon, handshake_dim\nfrom earth2studio.lexicon import E2STUDIO_VOCAB\nfrom earth2studio.utils import check_optional_dependencies\nfrom loguru import logger\n```\n\n**SPDX header (required at top of every .py file):**\n```python\n# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES.\n# SPDX-License-Identifier: Apache-2.0\n```\n\n**Canonical method order:**\n1. `__init__` 2. `input_coords` 3. `output_coords` (@batch_coords)\n4. `load_default_package` 5. `load_model` 6. `to` (optional)\n7. Private methods 8. `__call__` (@batch_func) 9. `_default_generator`\n10. `create_iterator`\n\n### Step 4 — Implement Coordinates\n\n**input_coords rules:**\n- `batch`: `np.empty(0)`\n- `time`: `np.empty(0)` (dynamic)\n- `lead_time`: starts at `np.timedelta64(0, \"h\")`\n- `lat`: 90 to -90 (north to south); this is the public Earth2Studio convention even if the source model uses the opposite order\n- `lon`: 0 to 360\n- If a checkpoint\u002Fmodel core expects south-to-north latitude, flip tensors internally before\u002Fafter the core model; do not expose flipped latitude in `input_coords` or `output_coords`\n- Map variables to `E2STUDIO_VOCAB` (282 entries in `earth2studio\u002Flexicon\u002Fbase.py`)\n\n**output_coords:** Use `handshake_dim`\u002F`handshake_coords` for input validation, then increment `lead_time`. Prefer a shared coordinate-check helper and call it from `output_coords`, `__call__`, and iterator setup before model execution.\n\n### Step 5 — Implement Forward Pass\n\n**`__call__`:** @batch_func decorated, shape (batch, time, lead_time, var, lat, lon).\nReshape to model format → call model → reshape back.\n\n**`create_iterator`:** MUST yield initial condition first (step 0).\nUse `front_hook`\u002F`rear_hook` for perturbation injection.\n\n### Step 6 — Implement Model Loading\n\n**`load_default_package`:** Lock HuggingFace URLs: `hf:\u002F\u002Forg\u002Frepo@commit`\n\n**`load_model`:** Use `package.resolve()`, `map_location=\"cpu\"`, `eval()` mode,\ndecorate with `@check_optional_dependencies()`.\n\n### Step 7 — Write Tests\n\n**File:** `test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py`\n\n**Required tests:**\n| Function | Purpose |\n|----------|---------|\n| `test_\u003Cmodel>_call` | Single forward pass (parametrize device\u002Ftime) |\n| `test_\u003Cmodel>_iter` | Iterator produces sequence |\n| `test_\u003Cmodel>_exceptions` | Invalid coords raise errors |\n| `test_\u003Cmodel>_package` | Real weights (`@pytest.mark.package`) |\n\nCreate `PhooModelName` dummy matching interface for mock tests.\n\n**Run tests:**\n```bash\nuv run pytest test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py -m \"not package\" -v\nuv run pytest test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py::test_\u003Cmodel>_package --package -v\n```\n\nDo not omit the package test. If arbitrary random inputs are not physically\nvalid for the real checkpoint, use a stable model-appropriate synthetic input\nwhile still loading real weights and running a forward pass.\n\n### Step 8 — Register Model (if requested)\n\n- Add to `earth2studio\u002Fmodels\u002Fpx\u002F__init__.py` (alphabetical)\n- Verify deps in pyproject.toml\n\n### Step 9 — Documentation\n\n- Add to `docs\u002Fmodules\u002Fmodels_px.rst` (alphabetical). This is required for\n  every new prognostic model so the API docs include the generated page.\n- Add to `docs\u002Fuserguide\u002Fabout\u002Finstall.md` (alphabetical tab) for the\n  model extra, even when the extra is empty. Include model-specific notes plus\n  both `pip install earth2studio[model-name]` and\n  `uv add earth2studio --extra model-name` instructions.\n- Update `CHANGELOG.md` under `### Added`. This is required for every new\n  prognostic model.\n\n**Format and lint:**\n```bash\nmake format && make lint && make license\n```\n\n### Step 10 - Validation (if requested)\n\nFollow `references\u002Fvalidation-guide.md`. Create uncommitted vanilla, E2S,\ncomparison, and sanity-check scripts; do not commit generated outputs or images.\nUse PR-safe placeholders for plots so the user can upload images manually.\n\n**[CONFIRM]** User must visually inspect plots before proceeding.\n\n### Step 11 - PR (if requested)\n\nFollow `references\u002Fvalidation-guide.md` and use:\n- `references\u002Fpr-body-template.md`\n- `references\u002Fpr-comment-template.md`\n\nBefore creating the PR, verify `pyproject.toml` has the model extra, the\n`all` extra includes it, install docs include both pip and uv commands, and\n`docs\u002Fmodules\u002Fmodels_px.rst` plus `CHANGELOG.md` are updated.\n\nDo not include machine names, absolute paths, device inventory, or uploaded image\nlinks in PR text. Use plot placeholders instead.\n\n---\n\n## Examples\n\n### Simple Identity Model\n```text\nUser: Create IdentityModel - returns input unchanged, 6h step, 181x360, vars: t2m, u10m, v10m, msl\n\nAgent: [reads SKILL.md, creates identity.py with triple inheritance,\n        creates test_identity.py, runs pytest, runs make format && lint]\n```\n\n### External Model (Pangu)\n```text\nUser: Add Pangu-Weather wrapper\n      GitHub: https:\u002F\u002Fgithub.com\u002F198808xc\u002FPangu-Weather\n\nAgent: [reads SKILL.md, fetches inference.py, creates pangu.py,\n        creates test_pangu.py, runs pytest]\n```\n\n---\n\n## Key Patterns\n\n### Coordinate Template\n```python\n@property\ndef input_coords(self) -> CoordSystem:\n    return CoordSystem({\n        \"batch\": np.empty(0),\n        \"time\": np.empty(0),\n        \"lead_time\": np.array([np.timedelta64(0, \"h\")]),\n        \"variable\": np.array([\"t2m\", \"u10m\", ...]),\n        # Public Earth2Studio convention is north-to-south latitude.\n        \"lat\": np.linspace(90, -90, 181),\n        \"lon\": np.linspace(0, 359, 360),\n    })\n\n@batch_coords()\ndef output_coords(self, input_coords: CoordSystem) -> CoordSystem:\n    output = input_coords.copy()\n    output[\"lead_time\"] = input_coords[\"lead_time\"] + np.timedelta64(6, \"h\")\n    return output\n```\n\n### Iterator Template\n```python\ndef create_iterator(self, x, coords):\n    yield x, coords  # Initial condition (step 0)\n    while True:\n        x, coords = self.front_hook(x, coords)\n        x, coords = self(x, coords)\n        x, coords = self.rear_hook(x, coords)\n        yield x, coords\n```\n\n---\n\n## Troubleshooting\n\n| Error | Solution |\n|-------|----------|\n| `OptionalDependencyFailure` | `uv add --optional \u003Cgroup> \u003Cpkg>` |\n| Coordinate handshake fails | Check `handshake_dim` indices match dim position |\n| Iterator wrong shapes | Debug reshape logic with random input |\n| `ModuleNotFoundError: pytest` | Use `uv run pytest` not `pytest` |\n\n---\n\n## Reminders\n\n**DO:**\n- Use `uv run python` for ALL Python commands\n- Use `loguru.logger`, never `print()`\n- Inherit `torch.nn.Module + AutoModelMixin + PrognosticMixin`\n- Yield initial condition first in `create_iterator`\n- Use `front_hook()`\u002F`rear_hook()` in `_default_generator`\n- Include SPDX header in every .py file\n\n**DON'T:**\n- Create general base classes for reuse\n- Commit API keys or comparison scripts\n- Read from `evals\u002Ftargets\u002F`\n",{"data":32,"body":41},{"name":4,"version":33,"license":23,"metadata":34,"description":6,"argument-hint":40},"0.16.0",{"author":35,"tags":36},"NVIDIA Earth-2 Team \u003Cagent-skills@nvidia.com>",[37,38,39],"earth2studio","prognostic-model","python","URL or local path to reference inference script (optional)",{"type":42,"children":43},"root",[44,53,63,164,247,253,258,264,355,371,378,383,498,502,508,514,527,535,541,546,566,606,619,625,644,650,666,674,689,697,782,790,813,821,907,913,921,1035,1082,1088,1103,1132,1138,1158,1201,1207,1220,1228,1324,1337,1345,1503,1508,1514,1535,1541,1605,1613,1661,1667,1679,1691,1697,1708,1729,1762,1767,1770,1776,1782,1792,1798,1807,1810,1816,1822,1973,1979,2042,2045,2051,2158,2161,2167,2175,2258,2266,2289],{"type":45,"tag":46,"props":47,"children":49},"element","h2",{"id":48},"quick-start-checklist",[50],{"type":51,"value":52},"text","Quick Start Checklist",{"type":45,"tag":54,"props":55,"children":56},"p",{},[57],{"type":45,"tag":58,"props":59,"children":60},"strong",{},[61],{"type":51,"value":62},"Do these steps IN ORDER. Do not skip any step.",{"type":45,"tag":64,"props":65,"children":68},"ul",{"className":66},[67],"contains-task-list",[69,83,92,110,126,141,150],{"type":45,"tag":70,"props":71,"children":74},"li",{"className":72},[73],"task-list-item",[75,81],{"type":45,"tag":76,"props":77,"children":80},"input",{"disabled":78,"type":79},true,"checkbox",[],{"type":51,"value":82}," Read this SKILL.md completely first",{"type":45,"tag":70,"props":84,"children":86},{"className":85},[73],[87,90],{"type":45,"tag":76,"props":88,"children":89},{"disabled":78,"type":79},[],{"type":51,"value":91}," Get reference script (Step 0)",{"type":45,"tag":70,"props":93,"children":95},{"className":94},[73],[96,99,101,108],{"type":45,"tag":76,"props":97,"children":98},{"disabled":78,"type":79},[],{"type":51,"value":100}," Create ",{"type":45,"tag":102,"props":103,"children":105},"code",{"className":104},[],[106],{"type":51,"value":107},"earth2studio\u002Fmodels\u002Fpx\u002F\u003Cname>.py",{"type":51,"value":109}," with triple inheritance",{"type":45,"tag":70,"props":111,"children":113},{"className":112},[73],[114,117,118,124],{"type":45,"tag":76,"props":115,"children":116},{"disabled":78,"type":79},[],{"type":51,"value":100},{"type":45,"tag":102,"props":119,"children":121},{"className":120},[],[122],{"type":51,"value":123},"test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py",{"type":51,"value":125}," with mock tests",{"type":45,"tag":70,"props":127,"children":129},{"className":128},[73],[130,133,135],{"type":45,"tag":76,"props":131,"children":132},{"disabled":78,"type":79},[],{"type":51,"value":134}," Run: ",{"type":45,"tag":102,"props":136,"children":138},{"className":137},[],[139],{"type":51,"value":140},"uv run pytest test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py -v",{"type":45,"tag":70,"props":142,"children":144},{"className":143},[73],[145,148],{"type":45,"tag":76,"props":146,"children":147},{"disabled":78,"type":79},[],{"type":51,"value":149}," Add\u002Fupdate model extra, install docs, API docs, and changelog (Steps 1-2, 9)",{"type":45,"tag":70,"props":151,"children":153},{"className":152},[73],[154,157,158],{"type":45,"tag":76,"props":155,"children":156},{"disabled":78,"type":79},[],{"type":51,"value":134},{"type":45,"tag":102,"props":159,"children":161},{"className":160},[],[162],{"type":51,"value":163},"make format && make lint",{"type":45,"tag":165,"props":166,"children":167},"blockquote",{},[168,186,228],{"type":45,"tag":54,"props":169,"children":170},{},[171,176,178,184],{"type":45,"tag":58,"props":172,"children":173},{},[174],{"type":51,"value":175},"⚠️ CRITICAL:",{"type":51,"value":177}," Always use ",{"type":45,"tag":102,"props":179,"children":181},{"className":180},[],[182],{"type":51,"value":183},"uv run",{"type":51,"value":185}," for Python commands:",{"type":45,"tag":64,"props":187,"children":188},{},[189,208],{"type":45,"tag":70,"props":190,"children":191},{},[192,194,200,202],{"type":51,"value":193},"✅ ",{"type":45,"tag":102,"props":195,"children":197},{"className":196},[],[198],{"type":51,"value":199},"uv run pytest ...",{"type":51,"value":201}," \u002F ",{"type":45,"tag":102,"props":203,"children":205},{"className":204},[],[206],{"type":51,"value":207},"uv run python ...",{"type":45,"tag":70,"props":209,"children":210},{},[211,213,219,220,226],{"type":51,"value":212},"❌ ",{"type":45,"tag":102,"props":214,"children":216},{"className":215},[],[217],{"type":51,"value":218},"pytest ...",{"type":51,"value":201},{"type":45,"tag":102,"props":221,"children":223},{"className":222},[],[224],{"type":51,"value":225},"python ...",{"type":51,"value":227}," (missing dependencies)",{"type":45,"tag":54,"props":229,"children":230},{},[231,236,238,245],{"type":45,"tag":58,"props":232,"children":233},{},[234],{"type":51,"value":235},"Stuck or wrong output:",{"type":51,"value":237}," Do not keep retrying the same fix. Follow\n",{"type":45,"tag":239,"props":240,"children":242},"a",{"href":241},"#self-improvement",[243],{"type":51,"value":244},"Self-Improvement",{"type":51,"value":246}," to patch this skill before continuing.",{"type":45,"tag":46,"props":248,"children":250},{"id":249},"purpose",[251],{"type":51,"value":252},"Purpose",{"type":45,"tag":54,"props":254,"children":255},{},[256],{"type":51,"value":257},"Implement a prognostic model wrapper connecting third-party ML weather models\nto Earth2Studio. Prognostic models time-integrate forward—given initial state,\nthey predict future states by stepping through time (e.g., 6-hour increments).",{"type":45,"tag":46,"props":259,"children":261},{"id":260},"workspace",[262],{"type":51,"value":263},"Workspace",{"type":45,"tag":265,"props":266,"children":267},"table",{},[268,287],{"type":45,"tag":269,"props":270,"children":271},"thead",{},[272],{"type":45,"tag":273,"props":274,"children":275},"tr",{},[276,282],{"type":45,"tag":277,"props":278,"children":279},"th",{},[280],{"type":51,"value":281},"Context",{"type":45,"tag":277,"props":283,"children":284},{},[285],{"type":51,"value":286},"Location",{"type":45,"tag":288,"props":289,"children":290},"tbody",{},[291,311,336],{"type":45,"tag":273,"props":292,"children":293},{},[294,300],{"type":45,"tag":295,"props":296,"children":297},"td",{},[298],{"type":51,"value":299},"Harbor eval",{"type":45,"tag":295,"props":301,"children":302},{},[303,305],{"type":51,"value":304},"Write to ",{"type":45,"tag":102,"props":306,"children":308},{"className":307},[],[309],{"type":51,"value":310},"\u002Fworkspace\u002Foutput\u002Fearth2studio\u002Fmodels\u002Fpx\u002F...",{"type":45,"tag":273,"props":312,"children":313},{},[314,325],{"type":45,"tag":295,"props":315,"children":316},{},[317,319],{"type":51,"value":318},"Harbor + ",{"type":45,"tag":102,"props":320,"children":322},{"className":321},[],[323],{"type":51,"value":324},"--copy-repo",{"type":45,"tag":295,"props":326,"children":327},{},[328,330],{"type":51,"value":329},"Full checkout at ",{"type":45,"tag":102,"props":331,"children":333},{"className":332},[],[334],{"type":51,"value":335},"\u002Fworkspace\u002Frepo",{"type":45,"tag":273,"props":337,"children":338},{},[339,344],{"type":45,"tag":295,"props":340,"children":341},{},[342],{"type":51,"value":343},"Local clone",{"type":45,"tag":295,"props":345,"children":346},{},[347,349],{"type":51,"value":348},"Directory with ",{"type":45,"tag":102,"props":350,"children":352},{"className":351},[],[353],{"type":51,"value":354},"pyproject.toml",{"type":45,"tag":54,"props":356,"children":357},{},[358,369],{"type":45,"tag":58,"props":359,"children":360},{},[361,363],{"type":51,"value":362},"Never read ",{"type":45,"tag":102,"props":364,"children":366},{"className":365},[],[367],{"type":51,"value":368},"evals\u002Ftargets\u002F",{"type":51,"value":370}," — grader references only.",{"type":45,"tag":372,"props":373,"children":375},"h3",{"id":374},"reference-files",[376],{"type":51,"value":377},"Reference Files",{"type":45,"tag":54,"props":379,"children":380},{},[381],{"type":51,"value":382},"Load on demand during the matching step:",{"type":45,"tag":265,"props":384,"children":385},{},[386,407],{"type":45,"tag":269,"props":387,"children":388},{},[389],{"type":45,"tag":273,"props":390,"children":391},{},[392,397,402],{"type":45,"tag":277,"props":393,"children":394},{},[395],{"type":51,"value":396},"File",{"type":45,"tag":277,"props":398,"children":399},{},[400],{"type":51,"value":401},"Content",{"type":45,"tag":277,"props":403,"children":404},{},[405],{"type":51,"value":406},"Load at",{"type":45,"tag":288,"props":408,"children":409},{},[410,432,454,476],{"type":45,"tag":273,"props":411,"children":412},{},[413,422,427],{"type":45,"tag":295,"props":414,"children":415},{},[416],{"type":45,"tag":102,"props":417,"children":419},{"className":418},[],[420],{"type":51,"value":421},"references\u002Fskeleton-template.py",{"type":45,"tag":295,"props":423,"children":424},{},[425],{"type":51,"value":426},"Full model skeleton with FILL comments",{"type":45,"tag":295,"props":428,"children":429},{},[430],{"type":51,"value":431},"Steps 3–6",{"type":45,"tag":273,"props":433,"children":434},{},[435,444,449],{"type":45,"tag":295,"props":436,"children":437},{},[438],{"type":45,"tag":102,"props":439,"children":441},{"className":440},[],[442],{"type":51,"value":443},"references\u002Fmethod-templates.py",{"type":45,"tag":295,"props":445,"children":446},{},[447],{"type":51,"value":448},"Canonical method implementations",{"type":45,"tag":295,"props":450,"children":451},{},[452],{"type":51,"value":453},"Steps 4–6",{"type":45,"tag":273,"props":455,"children":456},{},[457,466,471],{"type":45,"tag":295,"props":458,"children":459},{},[460],{"type":45,"tag":102,"props":461,"children":463},{"className":462},[],[464],{"type":51,"value":465},"references\u002Ftesting-guide.py",{"type":45,"tag":295,"props":467,"children":468},{},[469],{"type":51,"value":470},"Test skeleton and mock patterns",{"type":45,"tag":295,"props":472,"children":473},{},[474],{"type":51,"value":475},"Step 7",{"type":45,"tag":273,"props":477,"children":478},{},[479,488,493],{"type":45,"tag":295,"props":480,"children":481},{},[482],{"type":45,"tag":102,"props":483,"children":485},{"className":484},[],[486],{"type":51,"value":487},"references\u002Fvalidation-guide.md",{"type":45,"tag":295,"props":489,"children":490},{},[491],{"type":51,"value":492},"Comparison scripts, PR, code review",{"type":45,"tag":295,"props":494,"children":495},{},[496],{"type":51,"value":497},"Steps 10–11",{"type":45,"tag":499,"props":500,"children":501},"hr",{},[],{"type":45,"tag":46,"props":503,"children":505},{"id":504},"workflow-steps",[506],{"type":51,"value":507},"Workflow Steps",{"type":45,"tag":372,"props":509,"children":511},{"id":510},"step-0-get-reference-script",[512],{"type":51,"value":513},"Step 0 — Get Reference Script",{"type":45,"tag":54,"props":515,"children":516},{},[517,519,525],{"type":51,"value":518},"If ",{"type":45,"tag":102,"props":520,"children":522},{"className":521},[],[523],{"type":51,"value":524},"$ARGUMENTS",{"type":51,"value":526}," provided, use it. Otherwise ask:",{"type":45,"tag":165,"props":528,"children":529},{},[530],{"type":45,"tag":54,"props":531,"children":532},{},[533],{"type":51,"value":534},"Please provide a reference inference script URL\u002Fpath.",{"type":45,"tag":372,"props":536,"children":538},{"id":537},"step-1-analyze-propose-dependencies",[539],{"type":51,"value":540},"Step 1 — Analyze & Propose Dependencies",{"type":45,"tag":54,"props":542,"children":543},{},[544],{"type":51,"value":545},"Analyze: packages, architecture, I\u002FO shapes, time step, resolution, checkpoint.",{"type":45,"tag":54,"props":547,"children":548},{},[549,551,556,558,564],{"type":51,"value":550},"Propose ",{"type":45,"tag":102,"props":552,"children":554},{"className":553},[],[555],{"type":51,"value":354},{"type":51,"value":557}," group (alphabetical, add to ",{"type":45,"tag":102,"props":559,"children":561},{"className":560},[],[562],{"type":51,"value":563},"all",{"type":51,"value":565},"). Every\nprognostic model must have an optional dependency extra, even when no packages\nare required:",{"type":45,"tag":567,"props":568,"children":573},"pre",{"className":569,"code":570,"language":571,"meta":572,"style":572},"language-toml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","model-name = [\"package1>=version\", \"package2\"]\n# or, when no additional packages are required:\nmodel-name = []\n","toml","",[574],{"type":45,"tag":102,"props":575,"children":576},{"__ignoreMap":572},[577,588,597],{"type":45,"tag":578,"props":579,"children":582},"span",{"class":580,"line":581},"line",1,[583],{"type":45,"tag":578,"props":584,"children":585},{},[586],{"type":51,"value":587},"model-name = [\"package1>=version\", \"package2\"]\n",{"type":45,"tag":578,"props":589,"children":591},{"class":580,"line":590},2,[592],{"type":45,"tag":578,"props":593,"children":594},{},[595],{"type":51,"value":596},"# or, when no additional packages are required:\n",{"type":45,"tag":578,"props":598,"children":600},{"class":580,"line":599},3,[601],{"type":45,"tag":578,"props":602,"children":603},{},[604],{"type":51,"value":605},"model-name = []\n",{"type":45,"tag":54,"props":607,"children":608},{},[609,617],{"type":45,"tag":58,"props":610,"children":611},{},[612],{"type":45,"tag":578,"props":613,"children":614},{},[615],{"type":51,"value":616},"CONFIRM",{"type":51,"value":618}," Present dependencies and ask user to approve.",{"type":45,"tag":372,"props":620,"children":622},{"id":621},"step-2-add-dependencies",[623],{"type":51,"value":624},"Step 2 — Add Dependencies",{"type":45,"tag":54,"props":626,"children":627},{},[628,630,635,637,642],{"type":51,"value":629},"Edit ",{"type":45,"tag":102,"props":631,"children":633},{"className":632},[],[634],{"type":51,"value":354},{"type":51,"value":636},": add the model extra alphabetically, even if it is\nempty, and update the ",{"type":45,"tag":102,"props":638,"children":640},{"className":639},[],[641],{"type":51,"value":563},{"type":51,"value":643}," aggregate.",{"type":45,"tag":372,"props":645,"children":647},{"id":646},"step-3-create-model-file",[648],{"type":51,"value":649},"Step 3 — Create Model File",{"type":45,"tag":54,"props":651,"children":652},{},[653,658,660],{"type":45,"tag":58,"props":654,"children":655},{},[656],{"type":51,"value":657},"File:",{"type":51,"value":659}," ",{"type":45,"tag":102,"props":661,"children":663},{"className":662},[],[664],{"type":51,"value":665},"earth2studio\u002Fmodels\u002Fpx\u002F\u003Clowercase>.py",{"type":45,"tag":54,"props":667,"children":668},{},[669],{"type":45,"tag":58,"props":670,"children":671},{},[672],{"type":51,"value":673},"Required inheritance (all three):",{"type":45,"tag":567,"props":675,"children":678},{"className":676,"code":677,"language":39,"meta":572,"style":572},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","class ModelName(torch.nn.Module, AutoModelMixin, PrognosticMixin):\n",[679],{"type":45,"tag":102,"props":680,"children":681},{"__ignoreMap":572},[682],{"type":45,"tag":578,"props":683,"children":684},{"class":580,"line":581},[685],{"type":45,"tag":578,"props":686,"children":687},{},[688],{"type":51,"value":677},{"type":45,"tag":54,"props":690,"children":691},{},[692],{"type":45,"tag":58,"props":693,"children":694},{},[695],{"type":51,"value":696},"Required imports:",{"type":45,"tag":567,"props":698,"children":700},{"className":676,"code":699,"language":39,"meta":572,"style":572},"import numpy as np\nimport torch\nfrom earth2studio.models.auto import AutoModelMixin, Package\nfrom earth2studio.models.batch import batch_coords, batch_func\nfrom earth2studio.models.px.base import PrognosticMixin\nfrom earth2studio.models.utils import create_coords_from_lat_lon, handshake_dim\nfrom earth2studio.lexicon import E2STUDIO_VOCAB\nfrom earth2studio.utils import check_optional_dependencies\nfrom loguru import logger\n",[701],{"type":45,"tag":102,"props":702,"children":703},{"__ignoreMap":572},[704,712,720,728,737,746,755,764,773],{"type":45,"tag":578,"props":705,"children":706},{"class":580,"line":581},[707],{"type":45,"tag":578,"props":708,"children":709},{},[710],{"type":51,"value":711},"import numpy as np\n",{"type":45,"tag":578,"props":713,"children":714},{"class":580,"line":590},[715],{"type":45,"tag":578,"props":716,"children":717},{},[718],{"type":51,"value":719},"import torch\n",{"type":45,"tag":578,"props":721,"children":722},{"class":580,"line":599},[723],{"type":45,"tag":578,"props":724,"children":725},{},[726],{"type":51,"value":727},"from earth2studio.models.auto import AutoModelMixin, Package\n",{"type":45,"tag":578,"props":729,"children":731},{"class":580,"line":730},4,[732],{"type":45,"tag":578,"props":733,"children":734},{},[735],{"type":51,"value":736},"from earth2studio.models.batch import batch_coords, batch_func\n",{"type":45,"tag":578,"props":738,"children":740},{"class":580,"line":739},5,[741],{"type":45,"tag":578,"props":742,"children":743},{},[744],{"type":51,"value":745},"from earth2studio.models.px.base import PrognosticMixin\n",{"type":45,"tag":578,"props":747,"children":749},{"class":580,"line":748},6,[750],{"type":45,"tag":578,"props":751,"children":752},{},[753],{"type":51,"value":754},"from earth2studio.models.utils import create_coords_from_lat_lon, handshake_dim\n",{"type":45,"tag":578,"props":756,"children":758},{"class":580,"line":757},7,[759],{"type":45,"tag":578,"props":760,"children":761},{},[762],{"type":51,"value":763},"from earth2studio.lexicon import E2STUDIO_VOCAB\n",{"type":45,"tag":578,"props":765,"children":767},{"class":580,"line":766},8,[768],{"type":45,"tag":578,"props":769,"children":770},{},[771],{"type":51,"value":772},"from earth2studio.utils import check_optional_dependencies\n",{"type":45,"tag":578,"props":774,"children":776},{"class":580,"line":775},9,[777],{"type":45,"tag":578,"props":778,"children":779},{},[780],{"type":51,"value":781},"from loguru import logger\n",{"type":45,"tag":54,"props":783,"children":784},{},[785],{"type":45,"tag":58,"props":786,"children":787},{},[788],{"type":51,"value":789},"SPDX header (required at top of every .py file):",{"type":45,"tag":567,"props":791,"children":793},{"className":676,"code":792,"language":39,"meta":572,"style":572},"# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES.\n# SPDX-License-Identifier: Apache-2.0\n",[794],{"type":45,"tag":102,"props":795,"children":796},{"__ignoreMap":572},[797,805],{"type":45,"tag":578,"props":798,"children":799},{"class":580,"line":581},[800],{"type":45,"tag":578,"props":801,"children":802},{},[803],{"type":51,"value":804},"# SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION & AFFILIATES.\n",{"type":45,"tag":578,"props":806,"children":807},{"class":580,"line":590},[808],{"type":45,"tag":578,"props":809,"children":810},{},[811],{"type":51,"value":812},"# SPDX-License-Identifier: Apache-2.0\n",{"type":45,"tag":54,"props":814,"children":815},{},[816],{"type":45,"tag":58,"props":817,"children":818},{},[819],{"type":51,"value":820},"Canonical method order:",{"type":45,"tag":822,"props":823,"children":824},"ol",{},[825,852,879,898],{"type":45,"tag":70,"props":826,"children":827},{},[828,834,836,842,844,850],{"type":45,"tag":102,"props":829,"children":831},{"className":830},[],[832],{"type":51,"value":833},"__init__",{"type":51,"value":835}," 2. ",{"type":45,"tag":102,"props":837,"children":839},{"className":838},[],[840],{"type":51,"value":841},"input_coords",{"type":51,"value":843}," 3. ",{"type":45,"tag":102,"props":845,"children":847},{"className":846},[],[848],{"type":51,"value":849},"output_coords",{"type":51,"value":851}," (@batch_coords)",{"type":45,"tag":70,"props":853,"children":854},{},[855,861,863,869,871,877],{"type":45,"tag":102,"props":856,"children":858},{"className":857},[],[859],{"type":51,"value":860},"load_default_package",{"type":51,"value":862}," 5. ",{"type":45,"tag":102,"props":864,"children":866},{"className":865},[],[867],{"type":51,"value":868},"load_model",{"type":51,"value":870}," 6. ",{"type":45,"tag":102,"props":872,"children":874},{"className":873},[],[875],{"type":51,"value":876},"to",{"type":51,"value":878}," (optional)",{"type":45,"tag":70,"props":880,"children":881},{},[882,884,890,892],{"type":51,"value":883},"Private methods 8. ",{"type":45,"tag":102,"props":885,"children":887},{"className":886},[],[888],{"type":51,"value":889},"__call__",{"type":51,"value":891}," (@batch_func) 9. ",{"type":45,"tag":102,"props":893,"children":895},{"className":894},[],[896],{"type":51,"value":897},"_default_generator",{"type":45,"tag":70,"props":899,"children":900},{},[901],{"type":45,"tag":102,"props":902,"children":904},{"className":903},[],[905],{"type":51,"value":906},"create_iterator",{"type":45,"tag":372,"props":908,"children":910},{"id":909},"step-4-implement-coordinates",[911],{"type":51,"value":912},"Step 4 — Implement Coordinates",{"type":45,"tag":54,"props":914,"children":915},{},[916],{"type":45,"tag":58,"props":917,"children":918},{},[919],{"type":51,"value":920},"input_coords rules:",{"type":45,"tag":64,"props":922,"children":923},{},[924,941,958,975,986,997,1014],{"type":45,"tag":70,"props":925,"children":926},{},[927,933,935],{"type":45,"tag":102,"props":928,"children":930},{"className":929},[],[931],{"type":51,"value":932},"batch",{"type":51,"value":934},": ",{"type":45,"tag":102,"props":936,"children":938},{"className":937},[],[939],{"type":51,"value":940},"np.empty(0)",{"type":45,"tag":70,"props":942,"children":943},{},[944,950,951,956],{"type":45,"tag":102,"props":945,"children":947},{"className":946},[],[948],{"type":51,"value":949},"time",{"type":51,"value":934},{"type":45,"tag":102,"props":952,"children":954},{"className":953},[],[955],{"type":51,"value":940},{"type":51,"value":957}," (dynamic)",{"type":45,"tag":70,"props":959,"children":960},{},[961,967,969],{"type":45,"tag":102,"props":962,"children":964},{"className":963},[],[965],{"type":51,"value":966},"lead_time",{"type":51,"value":968},": starts at ",{"type":45,"tag":102,"props":970,"children":972},{"className":971},[],[973],{"type":51,"value":974},"np.timedelta64(0, \"h\")",{"type":45,"tag":70,"props":976,"children":977},{},[978,984],{"type":45,"tag":102,"props":979,"children":981},{"className":980},[],[982],{"type":51,"value":983},"lat",{"type":51,"value":985},": 90 to -90 (north to south); this is the public Earth2Studio convention even if the source model uses the opposite order",{"type":45,"tag":70,"props":987,"children":988},{},[989,995],{"type":45,"tag":102,"props":990,"children":992},{"className":991},[],[993],{"type":51,"value":994},"lon",{"type":51,"value":996},": 0 to 360",{"type":45,"tag":70,"props":998,"children":999},{},[1000,1002,1007,1009],{"type":51,"value":1001},"If a checkpoint\u002Fmodel core expects south-to-north latitude, flip tensors internally before\u002Fafter the core model; do not expose flipped latitude in ",{"type":45,"tag":102,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":51,"value":841},{"type":51,"value":1008}," or ",{"type":45,"tag":102,"props":1010,"children":1012},{"className":1011},[],[1013],{"type":51,"value":849},{"type":45,"tag":70,"props":1015,"children":1016},{},[1017,1019,1025,1027,1033],{"type":51,"value":1018},"Map variables to ",{"type":45,"tag":102,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":51,"value":1024},"E2STUDIO_VOCAB",{"type":51,"value":1026}," (282 entries in ",{"type":45,"tag":102,"props":1028,"children":1030},{"className":1029},[],[1031],{"type":51,"value":1032},"earth2studio\u002Flexicon\u002Fbase.py",{"type":51,"value":1034},")",{"type":45,"tag":54,"props":1036,"children":1037},{},[1038,1043,1045,1051,1053,1059,1061,1066,1068,1073,1075,1080],{"type":45,"tag":58,"props":1039,"children":1040},{},[1041],{"type":51,"value":1042},"output_coords:",{"type":51,"value":1044}," Use ",{"type":45,"tag":102,"props":1046,"children":1048},{"className":1047},[],[1049],{"type":51,"value":1050},"handshake_dim",{"type":51,"value":1052},"\u002F",{"type":45,"tag":102,"props":1054,"children":1056},{"className":1055},[],[1057],{"type":51,"value":1058},"handshake_coords",{"type":51,"value":1060}," for input validation, then increment ",{"type":45,"tag":102,"props":1062,"children":1064},{"className":1063},[],[1065],{"type":51,"value":966},{"type":51,"value":1067},". Prefer a shared coordinate-check helper and call it from ",{"type":45,"tag":102,"props":1069,"children":1071},{"className":1070},[],[1072],{"type":51,"value":849},{"type":51,"value":1074},", ",{"type":45,"tag":102,"props":1076,"children":1078},{"className":1077},[],[1079],{"type":51,"value":889},{"type":51,"value":1081},", and iterator setup before model execution.",{"type":45,"tag":372,"props":1083,"children":1085},{"id":1084},"step-5-implement-forward-pass",[1086],{"type":51,"value":1087},"Step 5 — Implement Forward Pass",{"type":45,"tag":54,"props":1089,"children":1090},{},[1091,1101],{"type":45,"tag":58,"props":1092,"children":1093},{},[1094,1099],{"type":45,"tag":102,"props":1095,"children":1097},{"className":1096},[],[1098],{"type":51,"value":889},{"type":51,"value":1100},":",{"type":51,"value":1102}," @batch_func decorated, shape (batch, time, lead_time, var, lat, lon).\nReshape to model format → call model → reshape back.",{"type":45,"tag":54,"props":1104,"children":1105},{},[1106,1115,1117,1123,1124,1130],{"type":45,"tag":58,"props":1107,"children":1108},{},[1109,1114],{"type":45,"tag":102,"props":1110,"children":1112},{"className":1111},[],[1113],{"type":51,"value":906},{"type":51,"value":1100},{"type":51,"value":1116}," MUST yield initial condition first (step 0).\nUse ",{"type":45,"tag":102,"props":1118,"children":1120},{"className":1119},[],[1121],{"type":51,"value":1122},"front_hook",{"type":51,"value":1052},{"type":45,"tag":102,"props":1125,"children":1127},{"className":1126},[],[1128],{"type":51,"value":1129},"rear_hook",{"type":51,"value":1131}," for perturbation injection.",{"type":45,"tag":372,"props":1133,"children":1135},{"id":1134},"step-6-implement-model-loading",[1136],{"type":51,"value":1137},"Step 6 — Implement Model Loading",{"type":45,"tag":54,"props":1139,"children":1140},{},[1141,1150,1152],{"type":45,"tag":58,"props":1142,"children":1143},{},[1144,1149],{"type":45,"tag":102,"props":1145,"children":1147},{"className":1146},[],[1148],{"type":51,"value":860},{"type":51,"value":1100},{"type":51,"value":1151}," Lock HuggingFace URLs: ",{"type":45,"tag":102,"props":1153,"children":1155},{"className":1154},[],[1156],{"type":51,"value":1157},"hf:\u002F\u002Forg\u002Frepo@commit",{"type":45,"tag":54,"props":1159,"children":1160},{},[1161,1170,1171,1177,1178,1184,1185,1191,1193,1199],{"type":45,"tag":58,"props":1162,"children":1163},{},[1164,1169],{"type":45,"tag":102,"props":1165,"children":1167},{"className":1166},[],[1168],{"type":51,"value":868},{"type":51,"value":1100},{"type":51,"value":1044},{"type":45,"tag":102,"props":1172,"children":1174},{"className":1173},[],[1175],{"type":51,"value":1176},"package.resolve()",{"type":51,"value":1074},{"type":45,"tag":102,"props":1179,"children":1181},{"className":1180},[],[1182],{"type":51,"value":1183},"map_location=\"cpu\"",{"type":51,"value":1074},{"type":45,"tag":102,"props":1186,"children":1188},{"className":1187},[],[1189],{"type":51,"value":1190},"eval()",{"type":51,"value":1192}," mode,\ndecorate with ",{"type":45,"tag":102,"props":1194,"children":1196},{"className":1195},[],[1197],{"type":51,"value":1198},"@check_optional_dependencies()",{"type":51,"value":1200},".",{"type":45,"tag":372,"props":1202,"children":1204},{"id":1203},"step-7-write-tests",[1205],{"type":51,"value":1206},"Step 7 — Write Tests",{"type":45,"tag":54,"props":1208,"children":1209},{},[1210,1214,1215],{"type":45,"tag":58,"props":1211,"children":1212},{},[1213],{"type":51,"value":657},{"type":51,"value":659},{"type":45,"tag":102,"props":1216,"children":1218},{"className":1217},[],[1219],{"type":51,"value":123},{"type":45,"tag":54,"props":1221,"children":1222},{},[1223],{"type":45,"tag":58,"props":1224,"children":1225},{},[1226],{"type":51,"value":1227},"Required tests:",{"type":45,"tag":265,"props":1229,"children":1230},{},[1231,1246],{"type":45,"tag":269,"props":1232,"children":1233},{},[1234],{"type":45,"tag":273,"props":1235,"children":1236},{},[1237,1242],{"type":45,"tag":277,"props":1238,"children":1239},{},[1240],{"type":51,"value":1241},"Function",{"type":45,"tag":277,"props":1243,"children":1244},{},[1245],{"type":51,"value":252},{"type":45,"tag":288,"props":1247,"children":1248},{},[1249,1266,1283,1300],{"type":45,"tag":273,"props":1250,"children":1251},{},[1252,1261],{"type":45,"tag":295,"props":1253,"children":1254},{},[1255],{"type":45,"tag":102,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":51,"value":1260},"test_\u003Cmodel>_call",{"type":45,"tag":295,"props":1262,"children":1263},{},[1264],{"type":51,"value":1265},"Single forward pass (parametrize device\u002Ftime)",{"type":45,"tag":273,"props":1267,"children":1268},{},[1269,1278],{"type":45,"tag":295,"props":1270,"children":1271},{},[1272],{"type":45,"tag":102,"props":1273,"children":1275},{"className":1274},[],[1276],{"type":51,"value":1277},"test_\u003Cmodel>_iter",{"type":45,"tag":295,"props":1279,"children":1280},{},[1281],{"type":51,"value":1282},"Iterator produces sequence",{"type":45,"tag":273,"props":1284,"children":1285},{},[1286,1295],{"type":45,"tag":295,"props":1287,"children":1288},{},[1289],{"type":45,"tag":102,"props":1290,"children":1292},{"className":1291},[],[1293],{"type":51,"value":1294},"test_\u003Cmodel>_exceptions",{"type":45,"tag":295,"props":1296,"children":1297},{},[1298],{"type":51,"value":1299},"Invalid coords raise errors",{"type":45,"tag":273,"props":1301,"children":1302},{},[1303,1312],{"type":45,"tag":295,"props":1304,"children":1305},{},[1306],{"type":45,"tag":102,"props":1307,"children":1309},{"className":1308},[],[1310],{"type":51,"value":1311},"test_\u003Cmodel>_package",{"type":45,"tag":295,"props":1313,"children":1314},{},[1315,1317,1323],{"type":51,"value":1316},"Real weights (",{"type":45,"tag":102,"props":1318,"children":1320},{"className":1319},[],[1321],{"type":51,"value":1322},"@pytest.mark.package",{"type":51,"value":1034},{"type":45,"tag":54,"props":1325,"children":1326},{},[1327,1329,1335],{"type":51,"value":1328},"Create ",{"type":45,"tag":102,"props":1330,"children":1332},{"className":1331},[],[1333],{"type":51,"value":1334},"PhooModelName",{"type":51,"value":1336}," dummy matching interface for mock tests.",{"type":45,"tag":54,"props":1338,"children":1339},{},[1340],{"type":45,"tag":58,"props":1341,"children":1342},{},[1343],{"type":51,"value":1344},"Run tests:",{"type":45,"tag":567,"props":1346,"children":1350},{"className":1347,"code":1348,"language":1349,"meta":572,"style":572},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","uv run pytest test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py -m \"not package\" -v\nuv run pytest test\u002Fmodels\u002Fpx\u002Ftest_\u003Cname>.py::test_\u003Cmodel>_package --package -v\n","bash",[1351],{"type":45,"tag":102,"props":1352,"children":1353},{"__ignoreMap":572},[1354,1431],{"type":45,"tag":578,"props":1355,"children":1356},{"class":580,"line":581},[1357,1363,1369,1374,1379,1385,1390,1396,1401,1406,1411,1416,1421,1426],{"type":45,"tag":578,"props":1358,"children":1360},{"style":1359},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1361],{"type":51,"value":1362},"uv",{"type":45,"tag":578,"props":1364,"children":1366},{"style":1365},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1367],{"type":51,"value":1368}," run",{"type":45,"tag":578,"props":1370,"children":1371},{"style":1365},[1372],{"type":51,"value":1373}," pytest",{"type":45,"tag":578,"props":1375,"children":1376},{"style":1365},[1377],{"type":51,"value":1378}," test\u002Fmodels\u002Fpx\u002Ftest_",{"type":45,"tag":578,"props":1380,"children":1382},{"style":1381},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1383],{"type":51,"value":1384},"\u003C",{"type":45,"tag":578,"props":1386,"children":1387},{"style":1365},[1388],{"type":51,"value":1389},"nam",{"type":45,"tag":578,"props":1391,"children":1393},{"style":1392},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1394],{"type":51,"value":1395},"e",{"type":45,"tag":578,"props":1397,"children":1398},{"style":1381},[1399],{"type":51,"value":1400},">",{"type":45,"tag":578,"props":1402,"children":1403},{"style":1365},[1404],{"type":51,"value":1405},".py",{"type":45,"tag":578,"props":1407,"children":1408},{"style":1365},[1409],{"type":51,"value":1410}," -m",{"type":45,"tag":578,"props":1412,"children":1413},{"style":1381},[1414],{"type":51,"value":1415}," \"",{"type":45,"tag":578,"props":1417,"children":1418},{"style":1365},[1419],{"type":51,"value":1420},"not package",{"type":45,"tag":578,"props":1422,"children":1423},{"style":1381},[1424],{"type":51,"value":1425},"\"",{"type":45,"tag":578,"props":1427,"children":1428},{"style":1365},[1429],{"type":51,"value":1430}," -v\n",{"type":45,"tag":578,"props":1432,"children":1433},{"class":580,"line":590},[1434,1438,1442,1446,1450,1454,1458,1462,1466,1471,1475,1480,1485,1489,1494,1499],{"type":45,"tag":578,"props":1435,"children":1436},{"style":1359},[1437],{"type":51,"value":1362},{"type":45,"tag":578,"props":1439,"children":1440},{"style":1365},[1441],{"type":51,"value":1368},{"type":45,"tag":578,"props":1443,"children":1444},{"style":1365},[1445],{"type":51,"value":1373},{"type":45,"tag":578,"props":1447,"children":1448},{"style":1365},[1449],{"type":51,"value":1378},{"type":45,"tag":578,"props":1451,"children":1452},{"style":1381},[1453],{"type":51,"value":1384},{"type":45,"tag":578,"props":1455,"children":1456},{"style":1365},[1457],{"type":51,"value":1389},{"type":45,"tag":578,"props":1459,"children":1460},{"style":1392},[1461],{"type":51,"value":1395},{"type":45,"tag":578,"props":1463,"children":1464},{"style":1381},[1465],{"type":51,"value":1400},{"type":45,"tag":578,"props":1467,"children":1468},{"style":1365},[1469],{"type":51,"value":1470},".py::test_",{"type":45,"tag":578,"props":1472,"children":1473},{"style":1381},[1474],{"type":51,"value":1384},{"type":45,"tag":578,"props":1476,"children":1477},{"style":1365},[1478],{"type":51,"value":1479},"mode",{"type":45,"tag":578,"props":1481,"children":1482},{"style":1392},[1483],{"type":51,"value":1484},"l",{"type":45,"tag":578,"props":1486,"children":1487},{"style":1381},[1488],{"type":51,"value":1400},{"type":45,"tag":578,"props":1490,"children":1491},{"style":1365},[1492],{"type":51,"value":1493},"_package",{"type":45,"tag":578,"props":1495,"children":1496},{"style":1365},[1497],{"type":51,"value":1498}," --package",{"type":45,"tag":578,"props":1500,"children":1501},{"style":1365},[1502],{"type":51,"value":1430},{"type":45,"tag":54,"props":1504,"children":1505},{},[1506],{"type":51,"value":1507},"Do not omit the package test. If arbitrary random inputs are not physically\nvalid for the real checkpoint, use a stable model-appropriate synthetic input\nwhile still loading real weights and running a forward pass.",{"type":45,"tag":372,"props":1509,"children":1511},{"id":1510},"step-8-register-model-if-requested",[1512],{"type":51,"value":1513},"Step 8 — Register Model (if requested)",{"type":45,"tag":64,"props":1515,"children":1516},{},[1517,1530],{"type":45,"tag":70,"props":1518,"children":1519},{},[1520,1522,1528],{"type":51,"value":1521},"Add to ",{"type":45,"tag":102,"props":1523,"children":1525},{"className":1524},[],[1526],{"type":51,"value":1527},"earth2studio\u002Fmodels\u002Fpx\u002F__init__.py",{"type":51,"value":1529}," (alphabetical)",{"type":45,"tag":70,"props":1531,"children":1532},{},[1533],{"type":51,"value":1534},"Verify deps in pyproject.toml",{"type":45,"tag":372,"props":1536,"children":1538},{"id":1537},"step-9-documentation",[1539],{"type":51,"value":1540},"Step 9 — Documentation",{"type":45,"tag":64,"props":1542,"children":1543},{},[1544,1556,1584],{"type":45,"tag":70,"props":1545,"children":1546},{},[1547,1548,1554],{"type":51,"value":1521},{"type":45,"tag":102,"props":1549,"children":1551},{"className":1550},[],[1552],{"type":51,"value":1553},"docs\u002Fmodules\u002Fmodels_px.rst",{"type":51,"value":1555}," (alphabetical). This is required for\nevery new prognostic model so the API docs include the generated page.",{"type":45,"tag":70,"props":1557,"children":1558},{},[1559,1560,1566,1568,1574,1576,1582],{"type":51,"value":1521},{"type":45,"tag":102,"props":1561,"children":1563},{"className":1562},[],[1564],{"type":51,"value":1565},"docs\u002Fuserguide\u002Fabout\u002Finstall.md",{"type":51,"value":1567}," (alphabetical tab) for the\nmodel extra, even when the extra is empty. Include model-specific notes plus\nboth ",{"type":45,"tag":102,"props":1569,"children":1571},{"className":1570},[],[1572],{"type":51,"value":1573},"pip install earth2studio[model-name]",{"type":51,"value":1575}," and\n",{"type":45,"tag":102,"props":1577,"children":1579},{"className":1578},[],[1580],{"type":51,"value":1581},"uv add earth2studio --extra model-name",{"type":51,"value":1583}," instructions.",{"type":45,"tag":70,"props":1585,"children":1586},{},[1587,1589,1595,1597,1603],{"type":51,"value":1588},"Update ",{"type":45,"tag":102,"props":1590,"children":1592},{"className":1591},[],[1593],{"type":51,"value":1594},"CHANGELOG.md",{"type":51,"value":1596}," under ",{"type":45,"tag":102,"props":1598,"children":1600},{"className":1599},[],[1601],{"type":51,"value":1602},"### Added",{"type":51,"value":1604},". This is required for every new\nprognostic model.",{"type":45,"tag":54,"props":1606,"children":1607},{},[1608],{"type":45,"tag":58,"props":1609,"children":1610},{},[1611],{"type":51,"value":1612},"Format and lint:",{"type":45,"tag":567,"props":1614,"children":1616},{"className":1347,"code":1615,"language":1349,"meta":572,"style":572},"make format && make lint && make license\n",[1617],{"type":45,"tag":102,"props":1618,"children":1619},{"__ignoreMap":572},[1620],{"type":45,"tag":578,"props":1621,"children":1622},{"class":580,"line":581},[1623,1628,1633,1638,1643,1648,1652,1656],{"type":45,"tag":578,"props":1624,"children":1625},{"style":1359},[1626],{"type":51,"value":1627},"make",{"type":45,"tag":578,"props":1629,"children":1630},{"style":1365},[1631],{"type":51,"value":1632}," format",{"type":45,"tag":578,"props":1634,"children":1635},{"style":1381},[1636],{"type":51,"value":1637}," &&",{"type":45,"tag":578,"props":1639,"children":1640},{"style":1359},[1641],{"type":51,"value":1642}," make",{"type":45,"tag":578,"props":1644,"children":1645},{"style":1365},[1646],{"type":51,"value":1647}," lint",{"type":45,"tag":578,"props":1649,"children":1650},{"style":1381},[1651],{"type":51,"value":1637},{"type":45,"tag":578,"props":1653,"children":1654},{"style":1359},[1655],{"type":51,"value":1642},{"type":45,"tag":578,"props":1657,"children":1658},{"style":1365},[1659],{"type":51,"value":1660}," license\n",{"type":45,"tag":372,"props":1662,"children":1664},{"id":1663},"step-10-validation-if-requested",[1665],{"type":51,"value":1666},"Step 10 - Validation (if requested)",{"type":45,"tag":54,"props":1668,"children":1669},{},[1670,1672,1677],{"type":51,"value":1671},"Follow ",{"type":45,"tag":102,"props":1673,"children":1675},{"className":1674},[],[1676],{"type":51,"value":487},{"type":51,"value":1678},". Create uncommitted vanilla, E2S,\ncomparison, and sanity-check scripts; do not commit generated outputs or images.\nUse PR-safe placeholders for plots so the user can upload images manually.",{"type":45,"tag":54,"props":1680,"children":1681},{},[1682,1689],{"type":45,"tag":58,"props":1683,"children":1684},{},[1685],{"type":45,"tag":578,"props":1686,"children":1687},{},[1688],{"type":51,"value":616},{"type":51,"value":1690}," User must visually inspect plots before proceeding.",{"type":45,"tag":372,"props":1692,"children":1694},{"id":1693},"step-11-pr-if-requested",[1695],{"type":51,"value":1696},"Step 11 - PR (if requested)",{"type":45,"tag":54,"props":1698,"children":1699},{},[1700,1701,1706],{"type":51,"value":1671},{"type":45,"tag":102,"props":1702,"children":1704},{"className":1703},[],[1705],{"type":51,"value":487},{"type":51,"value":1707}," and use:",{"type":45,"tag":64,"props":1709,"children":1710},{},[1711,1720],{"type":45,"tag":70,"props":1712,"children":1713},{},[1714],{"type":45,"tag":102,"props":1715,"children":1717},{"className":1716},[],[1718],{"type":51,"value":1719},"references\u002Fpr-body-template.md",{"type":45,"tag":70,"props":1721,"children":1722},{},[1723],{"type":45,"tag":102,"props":1724,"children":1726},{"className":1725},[],[1727],{"type":51,"value":1728},"references\u002Fpr-comment-template.md",{"type":45,"tag":54,"props":1730,"children":1731},{},[1732,1734,1739,1741,1746,1748,1753,1755,1760],{"type":51,"value":1733},"Before creating the PR, verify ",{"type":45,"tag":102,"props":1735,"children":1737},{"className":1736},[],[1738],{"type":51,"value":354},{"type":51,"value":1740}," has the model extra, the\n",{"type":45,"tag":102,"props":1742,"children":1744},{"className":1743},[],[1745],{"type":51,"value":563},{"type":51,"value":1747}," extra includes it, install docs include both pip and uv commands, and\n",{"type":45,"tag":102,"props":1749,"children":1751},{"className":1750},[],[1752],{"type":51,"value":1553},{"type":51,"value":1754}," plus ",{"type":45,"tag":102,"props":1756,"children":1758},{"className":1757},[],[1759],{"type":51,"value":1594},{"type":51,"value":1761}," are updated.",{"type":45,"tag":54,"props":1763,"children":1764},{},[1765],{"type":51,"value":1766},"Do not include machine names, absolute paths, device inventory, or uploaded image\nlinks in PR text. Use plot placeholders instead.",{"type":45,"tag":499,"props":1768,"children":1769},{},[],{"type":45,"tag":46,"props":1771,"children":1773},{"id":1772},"examples",[1774],{"type":51,"value":1775},"Examples",{"type":45,"tag":372,"props":1777,"children":1779},{"id":1778},"simple-identity-model",[1780],{"type":51,"value":1781},"Simple Identity Model",{"type":45,"tag":567,"props":1783,"children":1787},{"className":1784,"code":1786,"language":51,"meta":572},[1785],"language-text","User: Create IdentityModel - returns input unchanged, 6h step, 181x360, vars: t2m, u10m, v10m, msl\n\nAgent: [reads SKILL.md, creates identity.py with triple inheritance,\n        creates test_identity.py, runs pytest, runs make format && lint]\n",[1788],{"type":45,"tag":102,"props":1789,"children":1790},{"__ignoreMap":572},[1791],{"type":51,"value":1786},{"type":45,"tag":372,"props":1793,"children":1795},{"id":1794},"external-model-pangu",[1796],{"type":51,"value":1797},"External Model (Pangu)",{"type":45,"tag":567,"props":1799,"children":1802},{"className":1800,"code":1801,"language":51,"meta":572},[1785],"User: Add Pangu-Weather wrapper\n      GitHub: https:\u002F\u002Fgithub.com\u002F198808xc\u002FPangu-Weather\n\nAgent: [reads SKILL.md, fetches inference.py, creates pangu.py,\n        creates test_pangu.py, runs pytest]\n",[1803],{"type":45,"tag":102,"props":1804,"children":1805},{"__ignoreMap":572},[1806],{"type":51,"value":1801},{"type":45,"tag":499,"props":1808,"children":1809},{},[],{"type":45,"tag":46,"props":1811,"children":1813},{"id":1812},"key-patterns",[1814],{"type":51,"value":1815},"Key Patterns",{"type":45,"tag":372,"props":1817,"children":1819},{"id":1818},"coordinate-template",[1820],{"type":51,"value":1821},"Coordinate Template",{"type":45,"tag":567,"props":1823,"children":1825},{"className":676,"code":1824,"language":39,"meta":572,"style":572},"@property\ndef input_coords(self) -> CoordSystem:\n    return CoordSystem({\n        \"batch\": np.empty(0),\n        \"time\": np.empty(0),\n        \"lead_time\": np.array([np.timedelta64(0, \"h\")]),\n        \"variable\": np.array([\"t2m\", \"u10m\", ...]),\n        # Public Earth2Studio convention is north-to-south latitude.\n        \"lat\": np.linspace(90, -90, 181),\n        \"lon\": np.linspace(0, 359, 360),\n    })\n\n@batch_coords()\ndef output_coords(self, input_coords: CoordSystem) -> CoordSystem:\n    output = input_coords.copy()\n    output[\"lead_time\"] = input_coords[\"lead_time\"] + np.timedelta64(6, \"h\")\n    return output\n",[1826],{"type":45,"tag":102,"props":1827,"children":1828},{"__ignoreMap":572},[1829,1837,1845,1853,1861,1869,1877,1885,1893,1901,1910,1919,1928,1937,1946,1955,1964],{"type":45,"tag":578,"props":1830,"children":1831},{"class":580,"line":581},[1832],{"type":45,"tag":578,"props":1833,"children":1834},{},[1835],{"type":51,"value":1836},"@property\n",{"type":45,"tag":578,"props":1838,"children":1839},{"class":580,"line":590},[1840],{"type":45,"tag":578,"props":1841,"children":1842},{},[1843],{"type":51,"value":1844},"def input_coords(self) -> CoordSystem:\n",{"type":45,"tag":578,"props":1846,"children":1847},{"class":580,"line":599},[1848],{"type":45,"tag":578,"props":1849,"children":1850},{},[1851],{"type":51,"value":1852},"    return CoordSystem({\n",{"type":45,"tag":578,"props":1854,"children":1855},{"class":580,"line":730},[1856],{"type":45,"tag":578,"props":1857,"children":1858},{},[1859],{"type":51,"value":1860},"        \"batch\": np.empty(0),\n",{"type":45,"tag":578,"props":1862,"children":1863},{"class":580,"line":739},[1864],{"type":45,"tag":578,"props":1865,"children":1866},{},[1867],{"type":51,"value":1868},"        \"time\": np.empty(0),\n",{"type":45,"tag":578,"props":1870,"children":1871},{"class":580,"line":748},[1872],{"type":45,"tag":578,"props":1873,"children":1874},{},[1875],{"type":51,"value":1876},"        \"lead_time\": np.array([np.timedelta64(0, \"h\")]),\n",{"type":45,"tag":578,"props":1878,"children":1879},{"class":580,"line":757},[1880],{"type":45,"tag":578,"props":1881,"children":1882},{},[1883],{"type":51,"value":1884},"        \"variable\": np.array([\"t2m\", \"u10m\", ...]),\n",{"type":45,"tag":578,"props":1886,"children":1887},{"class":580,"line":766},[1888],{"type":45,"tag":578,"props":1889,"children":1890},{},[1891],{"type":51,"value":1892},"        # Public Earth2Studio convention is north-to-south latitude.\n",{"type":45,"tag":578,"props":1894,"children":1895},{"class":580,"line":775},[1896],{"type":45,"tag":578,"props":1897,"children":1898},{},[1899],{"type":51,"value":1900},"        \"lat\": np.linspace(90, -90, 181),\n",{"type":45,"tag":578,"props":1902,"children":1904},{"class":580,"line":1903},10,[1905],{"type":45,"tag":578,"props":1906,"children":1907},{},[1908],{"type":51,"value":1909},"        \"lon\": np.linspace(0, 359, 360),\n",{"type":45,"tag":578,"props":1911,"children":1913},{"class":580,"line":1912},11,[1914],{"type":45,"tag":578,"props":1915,"children":1916},{},[1917],{"type":51,"value":1918},"    })\n",{"type":45,"tag":578,"props":1920,"children":1922},{"class":580,"line":1921},12,[1923],{"type":45,"tag":578,"props":1924,"children":1925},{"emptyLinePlaceholder":78},[1926],{"type":51,"value":1927},"\n",{"type":45,"tag":578,"props":1929,"children":1931},{"class":580,"line":1930},13,[1932],{"type":45,"tag":578,"props":1933,"children":1934},{},[1935],{"type":51,"value":1936},"@batch_coords()\n",{"type":45,"tag":578,"props":1938,"children":1940},{"class":580,"line":1939},14,[1941],{"type":45,"tag":578,"props":1942,"children":1943},{},[1944],{"type":51,"value":1945},"def output_coords(self, input_coords: CoordSystem) -> CoordSystem:\n",{"type":45,"tag":578,"props":1947,"children":1949},{"class":580,"line":1948},15,[1950],{"type":45,"tag":578,"props":1951,"children":1952},{},[1953],{"type":51,"value":1954},"    output = input_coords.copy()\n",{"type":45,"tag":578,"props":1956,"children":1958},{"class":580,"line":1957},16,[1959],{"type":45,"tag":578,"props":1960,"children":1961},{},[1962],{"type":51,"value":1963},"    output[\"lead_time\"] = input_coords[\"lead_time\"] + np.timedelta64(6, \"h\")\n",{"type":45,"tag":578,"props":1965,"children":1967},{"class":580,"line":1966},17,[1968],{"type":45,"tag":578,"props":1969,"children":1970},{},[1971],{"type":51,"value":1972},"    return output\n",{"type":45,"tag":372,"props":1974,"children":1976},{"id":1975},"iterator-template",[1977],{"type":51,"value":1978},"Iterator Template",{"type":45,"tag":567,"props":1980,"children":1982},{"className":676,"code":1981,"language":39,"meta":572,"style":572},"def create_iterator(self, x, coords):\n    yield x, coords  # Initial condition (step 0)\n    while True:\n        x, coords = self.front_hook(x, coords)\n        x, coords = self(x, coords)\n        x, coords = self.rear_hook(x, coords)\n        yield x, coords\n",[1983],{"type":45,"tag":102,"props":1984,"children":1985},{"__ignoreMap":572},[1986,1994,2002,2010,2018,2026,2034],{"type":45,"tag":578,"props":1987,"children":1988},{"class":580,"line":581},[1989],{"type":45,"tag":578,"props":1990,"children":1991},{},[1992],{"type":51,"value":1993},"def create_iterator(self, x, coords):\n",{"type":45,"tag":578,"props":1995,"children":1996},{"class":580,"line":590},[1997],{"type":45,"tag":578,"props":1998,"children":1999},{},[2000],{"type":51,"value":2001},"    yield x, coords  # Initial condition (step 0)\n",{"type":45,"tag":578,"props":2003,"children":2004},{"class":580,"line":599},[2005],{"type":45,"tag":578,"props":2006,"children":2007},{},[2008],{"type":51,"value":2009},"    while True:\n",{"type":45,"tag":578,"props":2011,"children":2012},{"class":580,"line":730},[2013],{"type":45,"tag":578,"props":2014,"children":2015},{},[2016],{"type":51,"value":2017},"        x, coords = self.front_hook(x, coords)\n",{"type":45,"tag":578,"props":2019,"children":2020},{"class":580,"line":739},[2021],{"type":45,"tag":578,"props":2022,"children":2023},{},[2024],{"type":51,"value":2025},"        x, coords = self(x, coords)\n",{"type":45,"tag":578,"props":2027,"children":2028},{"class":580,"line":748},[2029],{"type":45,"tag":578,"props":2030,"children":2031},{},[2032],{"type":51,"value":2033},"        x, coords = self.rear_hook(x, coords)\n",{"type":45,"tag":578,"props":2035,"children":2036},{"class":580,"line":757},[2037],{"type":45,"tag":578,"props":2038,"children":2039},{},[2040],{"type":51,"value":2041},"        yield x, coords\n",{"type":45,"tag":499,"props":2043,"children":2044},{},[],{"type":45,"tag":46,"props":2046,"children":2048},{"id":2047},"troubleshooting",[2049],{"type":51,"value":2050},"Troubleshooting",{"type":45,"tag":265,"props":2052,"children":2053},{},[2054,2070],{"type":45,"tag":269,"props":2055,"children":2056},{},[2057],{"type":45,"tag":273,"props":2058,"children":2059},{},[2060,2065],{"type":45,"tag":277,"props":2061,"children":2062},{},[2063],{"type":51,"value":2064},"Error",{"type":45,"tag":277,"props":2066,"children":2067},{},[2068],{"type":51,"value":2069},"Solution",{"type":45,"tag":288,"props":2071,"children":2072},{},[2073,2094,2114,2127],{"type":45,"tag":273,"props":2074,"children":2075},{},[2076,2085],{"type":45,"tag":295,"props":2077,"children":2078},{},[2079],{"type":45,"tag":102,"props":2080,"children":2082},{"className":2081},[],[2083],{"type":51,"value":2084},"OptionalDependencyFailure",{"type":45,"tag":295,"props":2086,"children":2087},{},[2088],{"type":45,"tag":102,"props":2089,"children":2091},{"className":2090},[],[2092],{"type":51,"value":2093},"uv add --optional \u003Cgroup> \u003Cpkg>",{"type":45,"tag":273,"props":2095,"children":2096},{},[2097,2102],{"type":45,"tag":295,"props":2098,"children":2099},{},[2100],{"type":51,"value":2101},"Coordinate handshake fails",{"type":45,"tag":295,"props":2103,"children":2104},{},[2105,2107,2112],{"type":51,"value":2106},"Check ",{"type":45,"tag":102,"props":2108,"children":2110},{"className":2109},[],[2111],{"type":51,"value":1050},{"type":51,"value":2113}," indices match dim position",{"type":45,"tag":273,"props":2115,"children":2116},{},[2117,2122],{"type":45,"tag":295,"props":2118,"children":2119},{},[2120],{"type":51,"value":2121},"Iterator wrong shapes",{"type":45,"tag":295,"props":2123,"children":2124},{},[2125],{"type":51,"value":2126},"Debug reshape logic with random input",{"type":45,"tag":273,"props":2128,"children":2129},{},[2130,2139],{"type":45,"tag":295,"props":2131,"children":2132},{},[2133],{"type":45,"tag":102,"props":2134,"children":2136},{"className":2135},[],[2137],{"type":51,"value":2138},"ModuleNotFoundError: pytest",{"type":45,"tag":295,"props":2140,"children":2141},{},[2142,2144,2150,2152],{"type":51,"value":2143},"Use ",{"type":45,"tag":102,"props":2145,"children":2147},{"className":2146},[],[2148],{"type":51,"value":2149},"uv run pytest",{"type":51,"value":2151}," not ",{"type":45,"tag":102,"props":2153,"children":2155},{"className":2154},[],[2156],{"type":51,"value":2157},"pytest",{"type":45,"tag":499,"props":2159,"children":2160},{},[],{"type":45,"tag":46,"props":2162,"children":2164},{"id":2163},"reminders",[2165],{"type":51,"value":2166},"Reminders",{"type":45,"tag":54,"props":2168,"children":2169},{},[2170],{"type":45,"tag":58,"props":2171,"children":2172},{},[2173],{"type":51,"value":2174},"DO:",{"type":45,"tag":64,"props":2176,"children":2177},{},[2178,2190,2208,2219,2229,2253],{"type":45,"tag":70,"props":2179,"children":2180},{},[2181,2182,2188],{"type":51,"value":2143},{"type":45,"tag":102,"props":2183,"children":2185},{"className":2184},[],[2186],{"type":51,"value":2187},"uv run python",{"type":51,"value":2189}," for ALL Python commands",{"type":45,"tag":70,"props":2191,"children":2192},{},[2193,2194,2200,2202],{"type":51,"value":2143},{"type":45,"tag":102,"props":2195,"children":2197},{"className":2196},[],[2198],{"type":51,"value":2199},"loguru.logger",{"type":51,"value":2201},", never ",{"type":45,"tag":102,"props":2203,"children":2205},{"className":2204},[],[2206],{"type":51,"value":2207},"print()",{"type":45,"tag":70,"props":2209,"children":2210},{},[2211,2213],{"type":51,"value":2212},"Inherit ",{"type":45,"tag":102,"props":2214,"children":2216},{"className":2215},[],[2217],{"type":51,"value":2218},"torch.nn.Module + AutoModelMixin + PrognosticMixin",{"type":45,"tag":70,"props":2220,"children":2221},{},[2222,2224],{"type":51,"value":2223},"Yield initial condition first in ",{"type":45,"tag":102,"props":2225,"children":2227},{"className":2226},[],[2228],{"type":51,"value":906},{"type":45,"tag":70,"props":2230,"children":2231},{},[2232,2233,2239,2240,2246,2248],{"type":51,"value":2143},{"type":45,"tag":102,"props":2234,"children":2236},{"className":2235},[],[2237],{"type":51,"value":2238},"front_hook()",{"type":51,"value":1052},{"type":45,"tag":102,"props":2241,"children":2243},{"className":2242},[],[2244],{"type":51,"value":2245},"rear_hook()",{"type":51,"value":2247}," in ",{"type":45,"tag":102,"props":2249,"children":2251},{"className":2250},[],[2252],{"type":51,"value":897},{"type":45,"tag":70,"props":2254,"children":2255},{},[2256],{"type":51,"value":2257},"Include SPDX header in every .py file",{"type":45,"tag":54,"props":2259,"children":2260},{},[2261],{"type":45,"tag":58,"props":2262,"children":2263},{},[2264],{"type":51,"value":2265},"DON'T:",{"type":45,"tag":64,"props":2267,"children":2268},{},[2269,2274,2279],{"type":45,"tag":70,"props":2270,"children":2271},{},[2272],{"type":51,"value":2273},"Create general base classes for reuse",{"type":45,"tag":70,"props":2275,"children":2276},{},[2277],{"type":51,"value":2278},"Commit API keys or comparison scripts",{"type":45,"tag":70,"props":2280,"children":2281},{},[2282,2284],{"type":51,"value":2283},"Read from ",{"type":45,"tag":102,"props":2285,"children":2287},{"className":2286},[],[2288],{"type":51,"value":368},{"type":45,"tag":2290,"props":2291,"children":2292},"style",{},[2293],{"type":51,"value":2294},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2296,"total":2398},[2297,2314,2328,2342,2354,2371,2386],{"slug":2298,"name":2298,"fn":2299,"description":2300,"org":2301,"tags":2302,"stars":20,"repoUrl":21,"updatedAt":2313},"accelerated-computing-cudf","accelerate data processing with cuDF","Official NVIDIA-authored guidance for NVIDIA cuDF GPU DataFrames, pandas acceleration, dask-cuDF, ETL, joins, groupby, CSV\u002FParquet I\u002FO, nullable semantics, and multi-GPU DataFrame workloads.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2303,2306,2309,2310],{"name":2304,"slug":2305,"type":15},"Data Analysis","data-analysis",{"name":2307,"slug":2308,"type":15},"Data Engineering","data-engineering",{"name":9,"slug":8,"type":15},{"name":2311,"slug":2312,"type":15},"Performance","performance","2026-07-14T05:28:43.176466",{"slug":2315,"name":2315,"fn":2316,"description":2317,"org":2318,"tags":2319,"stars":20,"repoUrl":21,"updatedAt":2327},"aiq-deploy","deploy and manage NVIDIA AI-Q infrastructure","Use when asked to install, deploy, run, validate, troubleshoot, or stop NVIDIA AI-Q Blueprint infrastructure.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2320,2323,2326],{"name":2321,"slug":2322,"type":15},"Deployment","deployment",{"name":2324,"slug":2325,"type":15},"Infrastructure","infrastructure",{"name":9,"slug":8,"type":15},"2026-07-14T05:29:06.667109",{"slug":2329,"name":2329,"fn":2330,"description":2331,"org":2332,"tags":2333,"stars":20,"repoUrl":21,"updatedAt":2341},"aiq-research","conduct deep research with AI-Q","Use when asked to run deep research or AI-Q research through a reachable NVIDIA AI-Q Blueprint backend.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2334,2337,2338],{"name":2335,"slug":2336,"type":15},"Agents","agents",{"name":9,"slug":8,"type":15},{"name":2339,"slug":2340,"type":15},"Research","research","2026-07-14T05:28:06.816956",{"slug":2343,"name":2343,"fn":2344,"description":2345,"org":2346,"tags":2347,"stars":20,"repoUrl":21,"updatedAt":2353},"amc-run-sample-calibration","run AMC sample dataset calibration","Run end-to-end calibration on the shipped sample dataset (sdg_08_2_sample_data_010926.zip) against a running AMC microservice. Use when user says 'test sample dataset', 'run sample calibration', 'verify AMC install', or 'launch and test'.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2348,2349,2350],{"name":2304,"slug":2305,"type":15},{"name":9,"slug":8,"type":15},{"name":2351,"slug":2352,"type":15},"Testing","testing","2026-07-17T05:29:03.913266",{"slug":2355,"name":2355,"fn":2356,"description":2357,"org":2358,"tags":2359,"stars":20,"repoUrl":21,"updatedAt":2370},"amc-run-video-calibration","calibrate video datasets with AutoMagicCalib","Calibrate a new dataset from pre-recorded video files via the AutoMagicCalib REST API. Use when user has local MP4s and says 'calibrate my videos', 'run AMC on these videos', or similar. For RTSP\u002Flive streams, use amc-run-rtsp-calibration instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2360,2363,2366,2367],{"name":2361,"slug":2362,"type":15},"Automation","automation",{"name":2364,"slug":2365,"type":15},"Imaging","imaging",{"name":9,"slug":8,"type":15},{"name":2368,"slug":2369,"type":15},"Video","video","2026-07-17T05:28:53.905004",{"slug":2372,"name":2372,"fn":2373,"description":2374,"org":2375,"tags":2376,"stars":20,"repoUrl":21,"updatedAt":2385},"amc-setup-calibration-stack","deploy AutoMagicCalib microservice with Docker","Launch AutoMagicCalib microservice and web UI from NGC release images via Docker Compose. Use when user says 'deploy auto calibration', 'launch auto calibration', 'launch AMC', 'start MS+UI', or 'set up auto-magic-calib'. Requires NGC API key.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2377,2378,2381,2382],{"name":2321,"slug":2322,"type":15},{"name":2379,"slug":2380,"type":15},"Docker","docker",{"name":9,"slug":8,"type":15},{"name":2383,"slug":2384,"type":15},"Operations","operations","2026-07-17T05:28:56.913999",{"slug":2387,"name":2387,"fn":2388,"description":2389,"org":2390,"tags":2391,"stars":20,"repoUrl":21,"updatedAt":2397},"cudaq-guide","develop quantum applications with CUDA-Q","CUDA-Q onboarding guide for installation, test programs, GPU simulation, QPU hardware, and quantum applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2392,2393,2396],{"name":9,"slug":8,"type":15},{"name":2394,"slug":2395,"type":15},"Quantum Computing","quantum-computing",{"name":18,"slug":19,"type":15},"2026-07-14T05:26:58.898253",305,{"items":2400,"total":2550},[2401,2419,2434,2445,2457,2471,2484,2498,2509,2518,2532,2541],{"slug":2402,"name":2402,"fn":2403,"description":2404,"org":2405,"tags":2406,"stars":2416,"repoUrl":2417,"updatedAt":2418},"nemoclaw-user-guide","retrieve NemoClaw documentation and configuration","Guides human users' AI agents to the NemoClaw docs MCP server and canonical Fern documentation in Markdown form. Use when users ask how to install, configure, operate, troubleshoot, secure, or learn NemoClaw with an AI coding assistant. Trigger keywords - nemoclaw docs, use nemoclaw with ai agent, nemoclaw mcp docs, nemoclaw install help, nemoclaw quickstart, nemoclaw markdown docs, llms.txt, agent skills.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2407,2410,2413],{"name":2408,"slug":2409,"type":15},"Documentation","documentation",{"name":2411,"slug":2412,"type":15},"MCP","mcp",{"name":2414,"slug":2415,"type":15},"Search","search",21777,"https:\u002F\u002Fgithub.com\u002FNVIDIA\u002FNemoClaw","2026-07-20T06:00:01.461044",{"slug":2420,"name":2420,"fn":2421,"description":2422,"org":2423,"tags":2424,"stars":2431,"repoUrl":2432,"updatedAt":2433},"mcore-build-and-dependency","manage Megatron-LM development environments","Container-based dev environment setup and dependency management for Megatron-LM. Covers acquiring and launching the CI container, uv package management, and updating uv.lock.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2425,2428,2429],{"name":2426,"slug":2427,"type":15},"Containers","containers",{"name":2321,"slug":2322,"type":15},{"name":2430,"slug":39,"type":15},"Python",17049,"https:\u002F\u002Fgithub.com\u002FNVIDIA\u002FMegatron-LM","2026-07-27T06:06:11.249662",{"slug":2435,"name":2435,"fn":2436,"description":2437,"org":2438,"tags":2439,"stars":2431,"repoUrl":2432,"updatedAt":2444},"mcore-bump-base-image","update NVIDIA PyTorch base images","Bump the NVIDIA PyTorch base image (`nvcr.io\u002Fnvidia\u002Fpytorch:YY.MM-py3`) used by Megatron-LM CI. Covers the two pin sites (GitHub CI in `docker\u002F.ngc_version.dev` and GitLab CI in `.gitlab\u002Fstages\u002F01.build.yml`), the post-bump CI loop (re-run functional tests, refresh golden values, mark broken tests), and the gotchas that bit PRs",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2440,2443],{"name":2441,"slug":2442,"type":15},"CI\u002FCD","ci-cd",{"name":2321,"slug":2322,"type":15},"2026-07-14T05:25:59.97109",{"slug":2446,"name":2446,"fn":2447,"description":2448,"org":2449,"tags":2450,"stars":2431,"repoUrl":2432,"updatedAt":2456},"mcore-cicd","manage CI\u002FCD pipelines for Megatron-LM","CI\u002FCD reference for Megatron-LM. Covers CI pipeline structure, PR scope labels, triggering internal GitLab CI (which force-pushes the current branch to a pull-request\u002FBRANCH ref — always dry-run and verify the destination first; never run against shared or protected branches), and CI failure investigation.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2451,2452,2453],{"name":2441,"slug":2442,"type":15},{"name":2321,"slug":2322,"type":15},{"name":2454,"slug":2455,"type":15},"GitHub","github","2026-07-27T06:06:12.278222",{"slug":2458,"name":2458,"fn":2459,"description":2460,"org":2461,"tags":2462,"stars":2431,"repoUrl":2432,"updatedAt":2470},"mcore-create-issue","investigate CI failures and create issues","Investigate a failing GitHub Actions run or job and create a GitHub issue for the failure.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2463,2466,2467],{"name":2464,"slug":2465,"type":15},"Debugging","debugging",{"name":2454,"slug":2455,"type":15},{"name":2468,"slug":2469,"type":15},"Triage","triage","2026-07-14T05:25:57.442089",{"slug":2472,"name":2472,"fn":2473,"description":2474,"org":2475,"tags":2476,"stars":2431,"repoUrl":2432,"updatedAt":2483},"mcore-linting-and-formatting","lint and format Megatron-LM code","Linting and formatting for Megatron-LM. Covers running autoformat.sh, tools (ruff, black, isort, pylint, mypy), and code style rules.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2477,2480],{"name":2478,"slug":2479,"type":15},"Best Practices","best-practices",{"name":2481,"slug":2482,"type":15},"Code Analysis","code-analysis","2026-07-14T05:25:56.18433",{"slug":2485,"name":2485,"fn":2486,"description":2487,"org":2488,"tags":2489,"stars":2431,"repoUrl":2432,"updatedAt":2497},"mcore-migrate-gpt-to-hybrid","migrate Megatron-LM models to HybridModel","Migration guide for moving Megatron Core GPTModel checkpoints, model providers, training commands, and layer mappings to HybridModel.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2490,2493,2496],{"name":2491,"slug":2492,"type":15},"Machine Learning","machine-learning",{"name":2494,"slug":2495,"type":15},"Migration","migration",{"name":9,"slug":8,"type":15},"2026-07-17T06:07:11.777011",{"slug":2499,"name":2499,"fn":2500,"description":2501,"org":2502,"tags":2503,"stars":2431,"repoUrl":2432,"updatedAt":2508},"mcore-onboard-gb200-1node-tests","onboard functional tests for GB200","Onboard 1-node GitHub MR functional tests for GB200 from existing mr-scoped 2-node tests.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2504,2507],{"name":2505,"slug":2506,"type":15},"QA","qa",{"name":2351,"slug":2352,"type":15},"2026-07-14T05:25:53.673039",{"slug":2510,"name":2510,"fn":2511,"description":2512,"org":2513,"tags":2514,"stars":2431,"repoUrl":2432,"updatedAt":2517},"mcore-run-on-slurm","launch distributed training jobs on SLURM","How to launch distributed Megatron-LM training jobs on a SLURM cluster. Covers a minimal sbatch skeleton, environment-variable setup for torch.distributed.run, CUDA_DEVICE_MAX_CONNECTIONS rules across hardware and parallelism modes, container conventions, monitoring, and per-rank failure diagnosis.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2515,2516],{"name":2321,"slug":2322,"type":15},{"name":2324,"slug":2325,"type":15},"2026-07-14T05:25:49.362534",{"slug":2519,"name":2519,"fn":2520,"description":2521,"org":2522,"tags":2523,"stars":2431,"repoUrl":2432,"updatedAt":2531},"mcore-split-pr","split pull requests to reduce review load","Split a PR into multiple PRs to reduce the number of required CODEOWNERS reviewer groups.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2524,2527,2528],{"name":2525,"slug":2526,"type":15},"Code Review","code-review",{"name":2454,"slug":2455,"type":15},{"name":2529,"slug":2530,"type":15},"Pull Requests","pull-requests","2026-07-14T05:26:01.226578",{"slug":2533,"name":2533,"fn":2534,"description":2535,"org":2536,"tags":2537,"stars":2431,"repoUrl":2432,"updatedAt":2540},"mcore-testing","run and manage Megatron-LM tests","Test system for Megatron-LM. Covers test layout, recipe YAML structure, adding and running unit and functional tests, golden values, marker filters, and CI parity.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2538,2539],{"name":2505,"slug":2506,"type":15},{"name":2351,"slug":2352,"type":15},"2026-07-14T05:25:54.928983",{"slug":2542,"name":2542,"fn":2543,"description":2544,"org":2545,"tags":2546,"stars":2431,"repoUrl":2432,"updatedAt":2549},"nightly-sync","manage nightly main-to-dev sync workflows","Domain knowledge for the nightly main-to-dev sync workflow. Covers merge strategy, CI architecture, failure investigation, and known issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":9},[2547,2548],{"name":2361,"slug":2362,"type":15},{"name":2441,"slug":2442,"type":15},"2026-07-30T05:29:03.275638",496]