# Roo Code rules — enforce extensions (no legacy) and auto-migrate if detected ## 1. Hard mode: never run legacy - Disallow any pipeline using `bl_info` packaging/installation. - If no `blender_manifest.toml` exists, create it (see §3) and proceed as an **Extension** only. - If both `bl_info` and `blender_manifest.toml` exist, ignore `bl_info`. Fail if any legacy pack/install step is attempted. ## 2. Detection and fail-fast Treat as **legacy** if: - Missing `blender_manifest.toml`, **or** - Absolute intra-package imports (e.g., `import my_addon.module`), **or** - External deps not vendored as wheels in `./wheels/`. On detection → run §4 (migration). If migration can’t complete, fail with an actionable diff. ## 3. Required extension scaffold (write/update) Create `blender_manifest.toml` at repo root: ```toml schema_version = "1.0.0" id = "" # must equal the top-level package folder version = "1.0.0" name = "" type = "add-on" maintainer = " " blender_version_min = "4.2.0" license = "GPL-3.0-or-later" ``` Rules: - Single top-level Python package whose folder **equals** `id`. - `AddonPreferences` live in the root package and must be visible via Extensions. ## 4. Auto-migration (legacy → extension) 1. Move metadata from `bl_info` → `blender_manifest.toml`; **remove** `bl_info`. 2. Convert absolute intra-package imports to **relative** (`from . import x`). 3. Vendor Python deps as wheels under `./wheels/` (platform-specific if needed). 4. Enforce layout: ``` / ├─ / # Python package │ └─ __init__.py ├─ blender_manifest.toml └─ wheels/ # optional, *.whl ``` 5. Build only an **Extension** zip. ## 5. Build and install (extensions only) - Use Blender’s Extension Builder/CLI to produce `id-version.zip`. - Prohibit legacy zipping of parent directories. - Install-test on a **clean** profile: Preferences → Extensions → Install from Disk; enable/disable must pass. ## 6. CI guardrails - Lint manifest (keys, semver; `id == package folder`). - Assert **no** `bl_info` remains. - Block absolute intra-package imports. - Verify wheels exist for any bundled deps. - Headless smoke test: register → basic op → unregister without errors. ## 7. Preferences guarantee - Define `bpy.types.AddonPreferences` in the root package with `bl_idname = __package__`. - Must appear under **Edit → Preferences → Add-ons → [Your Add-on]**. - Access pattern: ```python prefs = bpy.context.preferences.addons[__package__].preferences ``` ## 8. Failure messages (actionable) - `Legacy detected: manifest created, imports converted, bl_info removed. Re-run build.` - `Extension layout invalid: 'id' must equal package folder.` - `Missing wheels: dependency X referenced but no wheel under ./wheels/.` ## 9. Explicitly blocked - No dual artifacts (legacy + extension) from the same commit. - No network installs or `pip` at runtime. - Artifacts must be self-contained.