Metadata-Version: 2.5
Name: papeete-actor-message
Version: 0.3.0
Summary: A per-actor data dictionary and message catalog contract for the Papeete ecosystem — papeete-actor-data/v0 and papeete-actor-message/v1.
Author-email: Papeete Consulting <yoann.remy@outlook.com>
License-Expression: MIT
License-File: LICENSE
Keywords: actor-model,agents,contract,data,message,modeling
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# papeete-actor-message

A per-actor data dictionary and message catalog for the [Papeete](https://github.com/papeete-hub)
ecosystem: `papeete-actor-data/v0` and `papeete-actor-message/v1`.

```
papeete-actor-message lint-data     ACTOR-DATA.YAML                         papeete-actor-data/v0
papeete-actor-message lint-messages ACTOR-MESSAGE.YAML [--data DATA.YAML]   papeete-actor-message/v1
papeete-actor-message contracts                                            which contracts this build enforces
```

```bash
pip install papeete-actor-message
```

## What it enforces

An actor's data dictionary — `actor-data.yaml` — declares a flat list of named, minimally-typed
items, and nothing else:

| Field | Says |
|---|---|
| `data` | names this contract: `papeete-actor-data/v0` |
| `items[].name` | the item's name, unique within this file |
| `items[].type` | one of `string`, `integer`, `number`, `boolean`, `enum`, `list` |
| `items[].values` | required when `type: enum`, disallowed otherwise |
| `items[].description` | free prose — what this datum is |

An actor's message catalog — `actor-message.yaml` — declares named messages that **reference**
data items only, grouped under an intent:

| Field | Says |
|---|---|
| `message` | names this contract: `papeete-actor-message/v1` |
| `messages[].name` | the message's name, unique within this file |
| `messages[].intent` | free prose — what this message is for |
| `messages[].references` | a list of data-item names, resolved against the sibling `actor-data.yaml` |
| `messages[].optional` | a subset of `references` not always present — the rest stay required by default |

A reference that resolves nowhere in the actor's own `actor-data.yaml` fails `lint-messages` —
the one referential-integrity rule this repo owns. The same data item may be referenced by any
number of messages within the same actor; a message never redefines, retypes, or inlines a
datum of its own.

`data:` and `message:` each name their own contract version, the same role `manifest:` plays on
`papeete-actor`'s `actor.yaml` — so each lineage can migrate (v0 → v1, warn-not-fail) on its own,
and a file declaring some other value is read and warned as UNMIGRATED rather than failed.

## Worked example

```yaml
# actor-data.yaml
data: papeete-actor-data/v0
items:
  - name: table_number
    type: integer
    description: The table where the order was placed.
  - name: dish
    type: string
    description: The name of the dish being ordered.
  - name: order_id
    type: string
    description: The unique identifier assigned to a placed order.
  - name: order_state
    type: enum
    values: [resolved, rejected, pending, unknown]
    description: The current lifecycle state of an order.
```

```yaml
# actor-message.yaml
message: papeete-actor-message/v1
messages:
  - name: take-order
    intent: Register what a customer wants to order, and where.
    references: [table_number, dish]
  - name: order-status
    intent: Ask for and report the current state of a previously placed order.
    references: [order_id, order_state]
```

See [`examples/waiter`](./examples/waiter) — the same cast `papeete-actor-synchronous-messaging`'s
own worked example uses, for continuity across the ecosystem's docs, not a functional dependency.

```bash
papeete-actor-message lint-data     examples/waiter/actor-data.yaml
papeete-actor-message lint-messages examples/waiter/actor-message.yaml
```

## What this repo deliberately does not do

**It carries no wire protocol.** Whether `order-status` above ends up riding a synchronous
`query`/`answer` exchange (today's only runnable case, owned by
[`papeete-actor-synchronous-messaging`](https://github.com/papeete-hub/papeete-actor-synchronous-messaging))
or a future asynchronous publication is a downstream binding's decision — never this catalog's.
A message here is exactly a name, an intent, and a list of data references; nothing about how it
is carried.

**It ships no runtime.** No actor class, no engine, no mailbox. `v0` is the contract alone —
schema files and the two lint gates that check them — the same sequencing `papeete-actor` itself
followed (identity shipped alone, before anything ran it).

**Data is scoped to one actor's own folder.** An external RDF/SHACL ontology governing data
items across actors is out of scope for now — the door is not closed to it later, but nothing
here anticipates its shape. See [ADR-PAM-0001](./adr/ADR-PAM-0001-data-and-message-catalogs.md)
and [ADR-PAM-0002](./adr/ADR-PAM-0002-a-reference-may-be-marked-optional.md) for the full
reasoning behind every choice above.

## The contract is in this repo

[`src/papeete_actor_message/schemas/`](./src/papeete_actor_message/schemas/) — ordinary
committed source. **The package IS the contract**, not a gate that goes looking for it, so a
build needs no network and no credential for the schemas themselves.

```bash
uv build   # no network, no token, no fetch step for either contract
```

## Licence

MIT.
