File size: 3,029 Bytes
796da7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 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/<your_domain>/
β”œβ”€β”€ __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 <your_domain>  # 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
"""<Your domain> β€” 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="<your_domain>",
    description="<one-line summary>",
    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).