# How to add a new domain PERMANENCE's framework is domain-agnostic. Adding a new domain (e.g. cloud ops, robotics, financial ops) is a matter of creating one new folder under `permanence/domains/` and implementing four small pieces. You should not need to edit any file outside that folder. ## Checklist ``` permanence/domains// ├── __init__.py # `from . import register` (4 lines) ├── register.py # calls core.register_domain(...) ├── actions.py # action definitions ├── tasks.py # task templates (TaskSpec + world_state_init_fn) └── simulators/ # (optional) stateful sandboxes like fs.py/git.py/db.py ``` Then add your domain to the import list in `permanence/domains/__init__.py`: ```python from . import meridian # noqa: F401 from . import devtools # noqa: F401 from . import # noqa: F401 ``` That's it. `import permanence` will now register your domain and `permanence.core.get_registry().summary()` will list your actions + tasks. ## What each file holds ### `__init__.py` ```python """ — one-line description.""" from . import register # noqa: F401 ``` ### `register.py` ```python from ...core import register_domain from .actions import ACTIONS # dict[str, ActionDefinition] from .tasks import TASK_TEMPLATES # dict[str, TaskTemplate] register_domain( name="", description="", actions=ACTIONS, task_templates=TASK_TEMPLATES, ) ``` ### `actions.py` Define `ACTIONS: Dict[str, ActionDefinition]`. Each action needs: - `action_id` — unique string (namespace with a prefix to avoid collisions) - `r_level_fn(world_state, params) -> int` — returns 1-5 based on world state - `consequences` — WorldStateMutation list (empty if domain owns mutations) See `permanence.domains.devtools.actions.ACTIONS` for a working example. ### `tasks.py` Define `TASK_TEMPLATES: Dict[str, TaskTemplate]`. Each template bundles: - `TaskSpec` (task_id, narrative, max_steps, success_fn) - `ScenarioGenerator` (parameter ranges for randomization) - `world_state_init_fn(sampled, scenario_id) -> WorldState` See `permanence.domains.devtools.tasks.task_templates()` for the DevTools pattern including per-episode randomization. ### `simulators/` (optional) If your domain needs stateful sandboxes (like DevTools' fs/git/db), put them here. Attach simulator handles to `WorldState` via optional fields (see `WorldState.fs`, `.git`, `.db`). Keep simulators isolated: no `subprocess`, no network, no real disk writes. Unit tests must assert this. ## Keep it clean - **Never import from another domain.** The whole point is independence. - **Namespace your action ids.** `fs_rm`, `git_push`, `deploy_prod` — not `rm`, `push`, `deploy`. - **Ship unit tests.** Isolation tests + reversibility gradient tests. - **Add a curriculum entry.** Update `CurriculumScheduler` to recognize your domain string (``"devtools"``, ``"meridian"``, or your new one).