Skip to content
Closed

Main #24

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5198e47
[fork demo — not for upstream] Attach Ramp Kit overlay with empty def…
cursoragent Sep 20, 2026
3d17d95
Merge pull request #2 from alex-16moro/cursor/overlay-empty-mcp-3eed
alex-16moro Sep 20, 2026
4acd877
[fork demo — not for upstream] Scaffold EulerLiteScheduler contract
cursoragent Sep 20, 2026
91da6d6
Merge pull request #4 from alex-16moro/cursor/scaffold-euler-lite-5588
alex-16moro Sep 20, 2026
b9ed91e
[fork demo — not for upstream] Implement EulerLiteScheduler Euler ODE…
cursoragent Sep 20, 2026
6cb0837
[fork demo — not for upstream] Export EulerLiteScheduler from public API
cursoragent Sep 20, 2026
55ba3c5
[fork demo — not for upstream] Add file-scoped Ramp Kit overlay CI
cursoragent Sep 20, 2026
2ed7f79
Merge pull request #6 from alex-16moro/cursor/overlay-fork-ci-3eed
alex-16moro Sep 20, 2026
ca51a71
[fork demo — not for upstream] Add EulerLiteScheduler API docs
cursoragent Sep 20, 2026
a361c3c
Merge pull request #7 from alex-16moro/cursor/docs-euler-lite-5588
alex-16moro Sep 20, 2026
70249b0
[fork demo — not for upstream] Scope /scaffold to registry-checked files
cursoragent Sep 20, 2026
80478b7
Merge pull request #10 from alex-16moro/cursor/prompt-registry-scope-…
alex-16moro Sep 20, 2026
0a1fdf4
[fork demo — not for upstream] Add HeunLiteScheduler scaffold
cursoragent Sep 20, 2026
f0a1a93
[fork demo — not for upstream] Wire stdio diffusers-docs MCP for Cloud
cursoragent Sep 20, 2026
6c44680
Merge pull request #12 from alex-16moro/cursor/export-euler-lite-5588
alex-16moro Sep 20, 2026
d1b5e9b
Merge pull request #11 from alex-16moro/cursor/heun-lite-scaffold-5588
alex-16moro Sep 20, 2026
fddec5e
Merge pull request #13 from alex-16moro/cursor/mcp-search-docs-availa…
alex-16moro Sep 20, 2026
f0349bd
[fork demo — not for upstream] Point overlay /scaffold at library CI
cursoragent Sep 20, 2026
a7b834e
Merge pull request #18 from alex-16moro/cursor/overlay-library-ci-sca…
alex-16moro Sep 20, 2026
b8e0af9
[fork demo — not for upstream] Empty the default overlay MCP
cursoragent Sep 20, 2026
1818c4e
[fork demo — not for upstream] Add PNDMLiteScheduler scaffold
cursoragent Sep 20, 2026
0397eea
Apply make style to existing lite scheduler files
cursoragent Sep 20, 2026
4741ae9
Merge pull request #20 from alex-16moro/cursor/pndm-lite-scaffold-2ce3
alex-16moro Sep 20, 2026
8d8b62c
Merge pull request #19 from alex-16moro/cursor/empty-default-mcp-3eed
alex-16moro Sep 20, 2026
49474cd
Fix Cursor setup for the Ramp Kit demo
alex-16moro Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .cursor/commands/scaffold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# /scaffold — first contribution on the REAL library checkout

Usage: `/scaffold <component> <Name>`

This workspace is `huggingface/diffusers` (fork). Overlay kit is `ramp-kit/`
(cloned from alex-16moro/diffuser_agent).

Root `AGENTS.md` and `.ai/` are Hugging Face's agent guide. **Read them. Do not
overwrite them.** They are how the library itself wants code to look (`make
style`, `make quality`, `# Copied from`, self-review). This overlay adds the
first-contribution recipe and a customer file-scoped gate. It does not replace
the library guide.

Do not disable or guard inherited GitHub workflows.

`$1` = component (`scheduler`). `$2` = PascalCase name without suffix (`PNDMLite`
→ `PNDMLiteScheduler`, `scheduling_pndm_lite.py`). If `scheduling_<snake>.py`
already exists, pick a new unused `$2`.

Copy the overlay templates. Do not start from library scheduler source. Keep
`TODO(engineer)` in `step()`.

## 0. Ground in the registry **and** the library guide

Read `ramp-kit/conventions/rules.yaml`. Blocking ids for this contribution:
SCHED001, SCHED002, SCHED003, REPRO001, DEVICE001, DEPR001, MUT001, TEST001,
TEST002.

Read root `AGENTS.md` and `.ai/` (library guide / review-rules / skills). Do
not overwrite them. Also read the reference source those files name. Optional
keyword search of this checkout's docs:

```bash
python3 ramp-kit/tools/docs_mcp_server.py --query "set_timesteps"
```

That CLI is a fallback, not a deliverable. Default `.cursor/mcp.json` has no
servers.

The templates already satisfy the overlay registry. Library CI (`make style` /
`make quality` / copies / dummies) is also required before the PR.

Stay inside `.cursorignore`. Do not read or copy
`ramp-kit/examples/candidate_scheduler/`.

## 1. Paths (library layout, not the kit stand-in)

Convert `$2` to snake_case (`PNDMLite` → `pndm_lite`). The class is `$2Scheduler`.

- Implementation: `src/diffusers/schedulers/scheduling_<snake>.py`
- Test: `tests/schedulers/test_scheduling_<snake>.py`

Do not overwrite `scheduling_euler_lite.py` or `scheduling_heun_lite.py`.

## 2. Copy from the overlay templates — replace every placeholder

- `ramp-kit/templates/scheduler/scheduling_TEMPLATE.py` → implementation
- Rename `TemplateScheduler` → `$2Scheduler`
- Keep `TODO(engineer)` in `step()`. Do not replace that placeholder.
- After the copy, the new files must not contain `TEMPLATE —`, `CHANGE_ME`,
`ChangeMeScheduler`, or `TemplateScheduler`.
- Add a `# Copied from` marker only when a block is actually copied.

## 3. Copy the contract test (TEST001 / TEST002)

Copy `ramp-kit/tests/_templates/scheduler_test.py`. Set `TARGET` and `CLASS`.
Replace every other template token so the test names `$2Scheduler`.

## 4. Register the scheduler (library public API)

Alphabetically insert `$2Scheduler` in:

- `src/diffusers/schedulers/__init__.py` — `_import_structure["scheduling_<snake>"]`
and the matching TYPE_CHECKING import
- `src/diffusers/__init__.py` — the torch schedulers lazy-import list and the
TYPE_CHECKING import from `.schedulers`

Then invoke (do not hand-write dummy classes):

```bash
python utils/check_dummies.py --fix_and_overwrite
```

## 5. File-scoped convention gate (never `--all`)

```bash
python3 ramp-kit/tools/convention_check.py src/diffusers/schedulers/scheduling_<snake>.py
python3 -m unittest tests.schedulers.test_scheduling_<snake> -v
```

Fix every **blocking** finding. Stop at 0 blocking. Do not edit `step()` math.

## 6. Library CI — invoke until green, then open the PR

These are the library's own checks from `AGENTS.md`. Iterate until all exit 0.
Do not reimplement them:

```bash
make style
make quality
python utils/check_copies.py && python utils/check_dummies.py && python utils/check_repo.py
python3 -m unittest tests.schedulers.test_scheduling_<snake> -v
```

Only then open a **draft** PR on this fork, **base `main`**. Never PR
huggingface/diffusers. Title prefix: `[fork demo — not for upstream]`.
16 changes: 16 additions & 0 deletions .cursor/commands/search-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# /search-docs — optional keyword search of THIS checkout's docs

Usage: `/search-docs <query>`

Prefer `ramp-kit/conventions/rules.yaml`, root `AGENTS.md`, `.ai/`, and the
reference source those files name. Default `.cursor/mcp.json` has no servers.

```bash
python3 ramp-kit/tools/docs_mcp_server.py --query $1
```

If `$1` is empty:

```bash
python3 ramp-kit/tools/docs_mcp_server.py --query "scheduler set_timesteps step SchedulerMixin register_to_config"
```
4 changes: 4 additions & 0 deletions .cursor/environment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"install": "bash .cursor/ramp-cloud-setup.sh install",
"start": "bash .cursor/ramp-cloud-setup.sh start"
}
11 changes: 11 additions & 0 deletions .cursor/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": 1,
"hooks": {
"afterFileEdit": [
{
"command": ".cursor/hooks/convention-gate.sh",
"timeout": 20
}
]
}
}
7 changes: 7 additions & 0 deletions .cursor/hooks/convention-gate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Cursor afterFileEdit hook. Project hooks run from the repo root.
# Reads the afterFileEdit JSON payload on stdin and runs the same
# convention gate as CI (`tools/convention_check.py`).
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
exec python3 "$ROOT/.cursor/hooks/convention_gate.py"
61 changes: 61 additions & 0 deletions .cursor/hooks/convention_gate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""afterFileEdit hook — run the same convention gate CI uses.

Cursor sends JSON on stdin:
{"file_path": "<absolute path>", "edits": [...]}

This is a notification (the write already happened). Findings are printed
to stderr so the agent can fix them immediately. We always exit 0 so a
red gate never crashes the editor loop; blocking findings still show up.
"""
from __future__ import annotations

import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
_kit_tools = None
for _cand in (ROOT / "ramp-kit" / "tools", ROOT / "tools"):
if (_cand / "convention_check.py").is_file():
_kit_tools = _cand
break
sys.path.insert(0, str(_kit_tools or (ROOT / "tools")))

from convention_check import check_file, load_rules, render_human # noqa: E402

# Don't fire the gate on the kit's own machinery or the teaching fixture
# (the fixture is scanned explicitly by `make demo`).
_SKIP_SUBSTR = (
"/tools/",
"/.cursor/",
"/_templates/",
"/templates/",
"/__pycache__/",
"/ramp-kit/examples/candidate_scheduler/",
)


def main() -> int:
raw = sys.stdin.read()
if not raw.strip():
return 0
try:
payload = json.loads(raw)
except json.JSONDecodeError:
return 0
file_path = payload.get("file_path") or ""
path = Path(file_path)
if path.suffix != ".py" or not path.is_file():
return 0
posix = path.as_posix()
if any(s in posix for s in _SKIP_SUBSTR):
return 0
findings = check_file(path, load_rules())
sys.stderr.write(render_human(findings, 1))
sys.stderr.flush()
return 0


if __name__ == "__main__":
raise SystemExit(main())
1 change: 1 addition & 0 deletions .cursor/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"mcpServers":{}}
29 changes: 29 additions & 0 deletions .cursor/ramp-cloud-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail

PHASE=${1:?Pass install or start}
case "$PHASE" in
install|start) ;;
*) echo 'Expected install or start.' >&2; exit 2 ;;
esac
REPO=$(git rev-parse --show-toplevel)
cd "$REPO"

if [ -e ramp-kit ] || [ -L ramp-kit ]; then
echo 'Legacy ramp-kit path detected. Create a fresh Cursor environment without the diffuser_agent repository or legacy install command. Do not reuse this Build for clean acceptance.' >&2
exit 2
fi

if [ ! -f .ramp-kit/runtime/bootstrap.sh ]; then
if [ "$PHASE" = install ]; then
echo 'Default-branch preparation complete. No external kit repository was cloned. Start the Ramp Kit session on ramp-demo; startup will prepare its installed .ramp-kit runtime.'
exit 0
fi
echo 'This branch has no installed .ramp-kit. Start the Ramp Kit session on ramp-demo.' >&2
exit 2
fi

if [ "$PHASE" = install ] || [ ! -x .ramp-venv/bin/python ]; then
bash .ramp-kit/runtime/bootstrap.sh "$REPO"
fi
.ramp-venv/bin/python .ramp-kit/run.py --repo "$REPO" doctor
40 changes: 40 additions & 0 deletions .cursor/rules/00-conventions.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
description: diffusers contribution conventions enforced by the Ramp Kit. Applied to all edits.
alwaysApply: true
---
<!-- GENERATED from conventions/rules.yaml by tools/build_projections.py. DO NOT EDIT. Run `make build`. -->

# diffusers conventions (registry v0.7.0)

You are contributing to `huggingface/diffusers`. Follow these conventions.
They mirror the project's own `.ai/` rules and are enforced by
`tools/convention_check.py` — the same gate that runs in CI, so producing
code that violates a **block** rule will fail the build.

The first contribution is what `conventions/rules.yaml` checks. Copy the
templates (`/scaffold`) and stop at 0 blocking findings from
`tools/convention_check.py` on the new files. Do not add files the
registry does not scan. Ground in this registry and, on the library,
`.ai/` plus reference source. Optional:
`python3 tools/docs_mcp_server.py --query "..."` — not a deliverable.

Do not pull in code or context from outside this repo's approved
boundaries (see `.cursorignore`).

## Blocking conventions (must satisfy)
- **REPRO001 — Randomness threads through a generator, never global RNG.** Use `randn_tensor(shape, generator=generator, device=..., dtype=...)` and thread `generator` through the call chain.
- **DEVICE001 — No hardcoded CUDA/device placement.** Respect the module's existing device: `.to(sample.device)` or accept a `device` argument.
- **DEPR001 — No deprecated/moved import paths.** Use the current import path shown in the check output.
- **MUT001 — No mutable default arguments.** Default to None and initialise inside the body.

## Advisory conventions (should satisfy)
- **DEPR002 — Avoid deprecated kwargs (verify per release).** Prefer the newer kwarg, but confirm against your pinned diffusers version.
- **COPY001 — # Copied from markers are well-formed.** Format: `# Copied from diffusers.<module.path>.<Symbol> with A->B`.
- **LOG001 — Library code logs, it does not print().** Use `logger = logging.get_logger(__name__)` and `logger.info(...)`.
- **DOC001 — Public methods have docstrings.** Add a Google-style docstring with Args/Returns.
- **CUST001 — No debugging leftovers committed.** Remove breakpoint()/pdb before committing.

Component-specific rules auto-attach when you open a matching file
(e.g. a scheduler). Start from `/scaffold` templates, not from a
library scheduler file. Use a `# Copied from` marker only when you
intentionally duplicate a small helper.
35 changes: 35 additions & 0 deletions .cursor/rules/10-scheduler.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
description: Extra diffusers conventions for schedulers.
globs: ["src/diffusers/schedulers/scheduling_*.py", "examples/**/scheduling_*.py", "tests/schedulers/test_scheduling_*.py"]
alwaysApply: false
---
<!-- GENERATED from conventions/rules.yaml by tools/build_projections.py. DO NOT EDIT. Run `make build`. -->

# Scheduler conventions (auto-attached to scheduler files)

### SCHED001 — Schedulers inherit SchedulerMixin and ConfigMixin (block, owner: architect)
Schedulers are swappable via ConfigMixin.from_config and serializable via SchedulerMixin. A scheduler that skips these can't be loaded, saved, or swapped like every other scheduler — it breaks the pipeline contract.
*How:* Declare `class XScheduler(SchedulerMixin, ConfigMixin):`.

### SCHED002 — Schedulers implement the step() / set_timesteps() contract (block, owner: architect)
Every denoising loop calls set_timesteps(...) once, then step(...) each iteration. VERIFIED against current source: DDPMScheduler and EulerDiscreteScheduler both define `set_timesteps(self, num_inference_steps, device=None, ...)` and `step(self, model_output, timestep, sample, generator=None, return_dict=True)`. The philosophy doc's older "set_num_inference_steps" name is stale; the code is canonical.
*How:* Implement `set_timesteps(self, num_inference_steps, device=None)` and `step(self, model_output, timestep, sample, generator=None, return_dict=True) -> SchedulerOutput`.

### SCHED003 — Scheduler __init__ is decorated with @register_to_config (block, owner: architect)
@register_to_config captures constructor args into the config so from_pretrained / save_pretrained round-trip correctly. Without it, config is empty and the scheduler cannot be reconstructed from the Hub.
*How:* Add `@register_to_config` directly above `def __init__`.

### IMPORT001 — Schedulers stay self-contained (no heavy util imports) (warn, owner: architect)
The single-file policy keeps schedulers readable and swappable. Pulling in pipeline internals or deep util chains couples them to the rest of the library and violates the philosophy reviewers enforce.
*How:* Copy the small helper in-file with a `# Copied from` marker instead of importing deep internals.

### TEST001 — New schedulers/models ship with a matching test file (block, owner: qa)
"No quality testing = no merge." A new scheduler with no test cannot move toward deployment. Presence is not enough: the test must actually exercise set_timesteps and step, otherwise a dummy file would satisfy the gate.
*How:* Generate a contract test from tests/_templates/scheduler_test.py that asserts set_timesteps and step.

### TEST002 — Scheduler tests assert behaviour, not just presence (block, owner: qa)
Presence of a test file is not enough. A test_* function with zero assertions is a dummy. New scheduler tests must include a same-seed determinism assertion and a shape/dtype assertion so CI actually pins the contract TEST001 only names.
*How:* Each test_* function must assert. Include same-seed determinism (torch.equal) and shape plus dtype checks (see tests/_templates/scheduler_test.py).

Reference implementation: `examples/scaffolded_scheduler/scheduling_ddpm_lite.py`.
Start from the scaffold: `/scaffold scheduler <Name>` — do not start from a blank file.
14 changes: 14 additions & 0 deletions .cursor/skills/search-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
name: search-docs
description: Optional docs CLI for this diffusers checkout. Prefer AGENTS.md, .ai/, and the gate. Default mcp.json has no servers.
---

# Search this library's docs

```bash
python3 ramp-kit/tools/docs_mcp_server.py --query "<the question>"
```

Cite provenance (`diffusers checkout` vs bundled snapshot).
`ramp-kit/conventions/rules.yaml` is the gate. Root `AGENTS.md` and `.ai/`
are the library guide. Default `.cursor/mcp.json` has no servers.
10 changes: 10 additions & 0 deletions .cursorignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Approved context boundary for the overlay agent.

# Known-bad teaching fixture (in the cloned kit). Gate it; do not copy it.
ramp-kit/examples/candidate_scheduler/

.git/
**/__pycache__/
**/*.pyc
.venv/
ramp-kit/.git/
Loading
Loading