Metadata-Version: 2.1
Name: dynos-core
Version: 0.1.2
Summary: Core symbolic-planning types and protocols shared by DYNOS packages
License: Apache-2.0
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: varname

# dynos-core

Pure-Python types for describing a planning domain. Predicates, transitions,
object types, and the world states they describe. `dynos-core` is the data
layer that every other DYNOS package shares.

This contains no planner, no executor, and no network code, it's just classes
that define a domain. The DYNOS backend reads these structures to
plan/execute/monitor/verify, clients read them to talk about goals, both share
the same in-memory representation.

Most users do not install `dynos-core` directly, You get it transitively when
you `pip install dynos-client` (or any package above it). Install it on its own
if you are authoring a new domain (or extending a new one, like when making
custom actions) and want the lowest-level types without pulling in the HTTP
client.

## Install

```bash
pip install dynos-core
```

Single dependency: `varname`. This is used to infer the names of objects being
created.

## Concepts

DYNOS describes the world as a set of named facts (fluents) about typed
objects. A goal is a state of those facts; a plan is a sequence of transitions
that move from one state to another. Actions are specific code implementations
of transitions.

### Fluents and ground atoms

A fluent is a named, parameterised proposition. `make_new_fluent` creates one;
calling it on specific objects creates a `GroundAtom`. This is a fluent
applied to particular arguments.

```python
from dynos_core import make_new_fluent, ObjectType, World

class Robot(ObjectType): ...
class Room(ObjectType): ...

at = make_new_fluent("at", robot=Robot, room=Room)
r = Robot("r1")
kitchen = Room("kitchen")

current = World({at(r, kitchen)})
print(at(r, kitchen) in current)   # True
```

A `World` is a frozenset of `GroundAtom` describing what is currently true. In
the current implementation, anything not in the set is false (closed-world
assumption), but more principled approaches are being designed.

### Object types and value fields

An `ObjectType` is a category of thing in the domain. For example, Robot, Room,
Zone, Coordinate. `ValueField` descriptors attach typed numeric/string fields:

```python
from dynos_core import ObjectType, ValueField

class Zone(ObjectType):
    altitude = ValueField(float)
    vertices = ValueField(list)
```

The class is pure Python; instances live in a backend-managed numeric database
at runtime, accessible through the same descriptor syntax
(`zone.altitude.get()` / `.set(70.0)`). `dynos-core` only declares the schema.

### Transitions

A `Transition` is an action *schema*: name, parameter type, preconditions,
effects. It says nothing about how the action runs.

```python
from dynos_core import Transition, TransitionParams

class GotoParams(TransitionParams):
    start: Room
    end: Room

goto = Transition("goto", params_type=GotoParams).define(
    preconditions=[at(GotoParams.start)],
    adds=[at(GotoParams.end)],
    removes=[at(GotoParams.start)],
)
```

The `define()` call stores the symbolic spec on the transition. The `dynos`
backend extends `Transition` with cost callbacks, applicability checks, and
execution hooks; this package's `Transition` is just data.

### Extensions

`extend_object_type` and `extend_transition_params` add fields after the class
is declared. This supports the *publish-stub* pattern: a domain package
declares a small public schema; the backend extends it with private fields at
import time. The public release strips the extension calls so users see only
the public surface.

```python
from dynos_core.extension import extend_object_type
extend_object_type(Zone, depth=ValueField(float))   # backend-only addition
```

See `extension.py` for the full rules (additive only, must run before any plan construction, etc.).

## What dynos-core does NOT do

- No planner. The actual planning lives in the `dynos` backend (not on PyPI).
- No `@Action` / `@Belief` / `@Script` decorators. Those run code; this package
  is data only. They live in the backend (and you import them from
  `dynos.databases.typed_action` when building a backend; or via the
  conditional-import pattern documented in `dynos-client`'s README when
  authoring client-only code).
- No network or robot connectivity. That's `dynos-client`.

## Public API

| Symbol                                  | Purpose                                                                    |
|-----------------------------------------|----------------------------------------------------------------------------|
| `GroundAtom`                            | A fluent applied to specific objects; the leaf of the symbolic state tree. |
| `World`                                 | Frozenset of `GroundAtom`; one snapshot of the symbolic state.             |
| `FluentBase`                            | Base class for fluents (rarely instantiated directly).                     |
| `make_new_fluent(name, **types)`        | Factory: returns a callable that produces `GroundAtom`.                    |
| `make_new_object(type, name, **fields)` | Factory: registers an `ObjectType` instance with the numeric database.     |
| `Transition`                            | Action schema (preconditions, effects, parameter type).                    |
| `TransitionParams`                      | Base class for typed parameter dataclasses.                                |
| `PrimitiveAction`                       | Frozen `(action_name, parameters)` pair — what flows over the wire.        |
| `ObjectType`                            | Base class for typed domain entities.                                      |
| `SymbolicObject`                        | An instance of an `ObjectType`.                                            |
| `ValueField`                            | Descriptor for typed numeric/string attributes on `ObjectType`.            |

## Next

To talk to a running DYNOS backend, install `dynos-client`. To get the Sentry
survey vocabulary, install `dynos-sentry-domain`. The walkthrough at
`user_guide.md` ties them together end-to-end.
