Skip to content

Releases: LunarCommand/openarmature-python

v0.3.0

28 Apr 20:05
d53fefc

Choose a tag to compare

Spec v0.2 / proposal 0002: explicit subgraph input/output mapping.

  • ExplicitMapping(inputs=..., outputs=...) projection strategy as a built-in alternative to writing a custom ProjectionStrategy.
  • New mapping_references_undeclared_field compile error category for inputs/outputs that name fields absent from the relevant schema.
  • ProjectionStrategy.validate is an optional duck-typed compile hook — declarative strategies (ExplicitMapping) expose it; imperative custom projections aren't forced to write a no-op.
  • Spec submodule pinned at v0.2.0.

See the proposal for design rationale.

v0.2.0

23 Apr 06:20

Choose a tag to compare

API ergonomics release. Two improvements landed:

  1. Method renames — the two "non-default" builder methods now name themselves explicitly at the call site.
  2. GenericsGraphBuilder and CompiledGraph carry the concrete State subclass through at type-check time, so cast(MyState, ...) is no longer needed on invoke() returns or projection arguments.

No spec-behavior changes; conformance fixtures continue to pass. Targets openarmature-spec v0.1.1.

Breaking changes

```diff
-builder.add_subgraph("research", research_subgraph, projection=MyProjection())
+builder.add_subgraph_node("research", research_subgraph, projection=MyProjection())

-builder.add_conditional("classify", route_fn)
+builder.add_conditional_edge("classify", route_fn)
```

Rationale: align names with what they add. `add_subgraph_node` pairs with `add_node` as the non-default node variant; `add_conditional_edge` pairs with `add_edge` as the non-default edge variant.

What's new: generic state typing (PEP 695)

`GraphBuilder`, `CompiledGraph`, `Node`, `FunctionNode`, `ConditionalEdge`, `SubgraphNode`, and `ProjectionStrategy` are all parameterized on a `StateT`-bound TypeVar.

```python
graph: CompiledGraph[MyState] = (
GraphBuilder(MyState)
.add_node("step", my_node)
.add_edge("step", END)
.set_entry("step")
.compile()
)

final = await graph.invoke(MyState(topic="..."))

final is typed MyState — field access works without cast()

print(final.topic)
```

Custom projections type their signatures directly:

```python
class MyProjection:
def project_in(
self,
parent_state: MyParentState,
subgraph_state_cls: type[MyChildState],
) -> MyChildState:
return subgraph_state_cls(topic=parent_state.topic)
```

Protocol is structural — no inheritance required.

See also

  • Demo projects: openarmature-examples — `01-linear-pipeline` (minimal graph) and `02-routing-and-subgraphs` (conditional routing + subgraph + custom projection)
  • Merged: #2 (renames), #3 (generics)

v0.1.0

23 Apr 06:25
e8f5de8

Choose a tag to compare

Initial graph engine implementation. Targets openarmature-spec v0.1.1.

Included

  • Typed `State` schema (frozen, strict) with per-field reducers (`last_write_wins`, `append`, `merge`)
  • Static and conditional edges; `END` sentinel
  • Subgraphs via `add_subgraph` with pluggable `ProjectionStrategy` (default: `FieldNameMatching`)
  • Compile-time structural validation: `NoDeclaredEntry`, `UnreachableNode`, `DanglingEdge`, `MultipleOutgoingEdges`, `ConflictingReducers`
  • Runtime error categories: `NodeException`, `EdgeException`, `ReducerError`, `RoutingError`, `StateValidationError` (all but the last carry `recoverable_state`)
  • Spec conformance fixtures 001–010 passing

Note

Tag backfilled after v0.2.0 for version-history symmetry with openarmature-spec. No one was consuming v0.1.0 at the time; see v0.2.0 for the first release intended for external pinning.