Skip to content

Commit 9f122c6

Browse files
Pin spec v0.55.1 and adopt proposal 0065 (#158)
Advance the pinned spec submodule from v0.54.0 to v0.55.1, adopting proposal 0065 (failure-isolation cause fidelity at non-node placements). The 0065 runtime behavior already shipped earlier in the cycle; this marks it implemented in conformance.toml and wires its conformance fixture 064, which passes all three cases (instance, branch, and uncategorized-cause sites) against the merged engine fix. Two test-harness gaps that fixture 064 is the first to hit are closed: the cases-shape runner now threads a shared plural subgraphs block into each case, and the CasesFixture parser model accepts subgraphs at the top level. The pin is v0.55.1 rather than v0.55.0 because v0.55.1 adds an observability span-links text reconciliation with no python-observable change. Sync the three spec-version declarations, regenerate AGENTS.md, and add the consolidated pin-journey changelog note.
1 parent fc69aaa commit 9f122c6

9 files changed

Lines changed: 54 additions & 27 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). The
1414
### Changed
1515

1616
- **`RetryMiddleware` now takes a `RetryConfig` record** instead of individual constructor kwargs (proposal 0050 prep). The four retry settings (`max_attempts` / `classifier` / `backoff` / `on_retry`, each optional) move onto a frozen `RetryConfig`; construct as `RetryMiddleware(RetryConfig(max_attempts=...))`, while bare `RetryMiddleware()` still applies the defaults. This is a breaking change to the `RetryMiddleware` constructor. The record is the same shape the upcoming call-level `complete(retry=...)` parameter will accept, so one retry config serves both the per-node and per-call layers. `None` fields resolve to the canonical defaults (`default_classifier` / `exponential_jitter_backoff`) at use, preserving the prior behavior.
17-
- **Failure-isolation events report the originating cause's category at non-node placements** (proposal 0065, pipeline-utilities §6.3). When `FailureIsolationMiddleware` runs as instance middleware (§9.7), branch middleware (§11.7), or parent-node middleware on a fan-out / parallel-branches node, the graph engine has already wrapped the originating error as a `node_exception` carrier before the middleware catches it. `FailureIsolatedEvent.caught_exception.category` now resolves through that carrier (and any nested carriers) to the nearest categorized originating cause and reports its category instead of the masking `node_exception`, so the reported category agrees with what the §6.1 retry classifier acted on. For example, an instance whose retries exhaust on `provider_unavailable` now surfaces `provider_unavailable` rather than `node_exception`. The `message` tracks the resolved cause for category/message coherence. Node-level placement was already faithful and is unchanged, and catch/degrade behavior is unchanged at every site (only the event's reported cause changes). The wrapped-instance/branch lineage SHOULD (`fan_out_index` / `branch_name`) is deferred to a follow-up, since it needs the engine to surface per-instance identity to the wrapping-site middleware.
18-
- **Observer privacy flag `disable_llm_payload` renamed to `disable_provider_payload`** (proposal 0059, observability §5.5.4, spec v0.54.0). The observer-level flag on both bundled observers (`OTelObserver` and `LangfuseObserver`) is renamed, and its scope broadens from LLM-completion payload to any provider-call payload (LLM completion today; embedding and rerank when those land). This is a breaking change to both observer constructors: config passing `disable_llm_payload=True` (or `False`) updates to `disable_provider_payload=...` with no other change. The default stays `True` (payload suppressed), and the gating behavior for `LlmCompletionEvent` / `LlmFailedEvent` rendering is unchanged at every existing site. The rename is the only part of proposal 0059 adopted this cycle: the retrieval-provider capability itself (the `EmbeddingProvider` protocol, the `EmbeddingEvent` / `EmbeddingFailedEvent` typed variants, and the embedding span / observation mapping) is not yet implemented and rides as `not-yet` in `conformance.toml`. The §5.5.4 rename touches existing LLM-payload gating, so it lands with the pin. Pinned spec advances v0.53.0 → v0.54.0.
17+
- **Failure-isolation events report the originating cause's category at non-node placements** (proposal 0065, pipeline-utilities §6.3). When `FailureIsolationMiddleware` runs as instance middleware (§9.7), branch middleware (§11.7), or parent-node middleware on a fan-out / parallel-branches node, the graph engine has already wrapped the originating error as a `node_exception` carrier before the middleware catches it. `FailureIsolatedEvent.caught_exception.category` now resolves through that carrier (and any nested carriers) to the nearest categorized originating cause and reports its category instead of the masking `node_exception`, so the reported category agrees with what the §6.1 retry classifier acted on. For example, an instance whose retries exhaust on `provider_unavailable` now surfaces `provider_unavailable` rather than `node_exception`. The `message` tracks the resolved cause for category/message coherence. Node-level placement was already faithful and is unchanged, and catch/degrade behavior is unchanged at every site (only the event's reported cause changes). The wrapped-instance/branch lineage SHOULD (`fan_out_index` / `branch_name`) is deferred to a follow-up, since it needs the engine to surface per-instance identity to the wrapping-site middleware. `conformance.toml` marks proposal 0065 `implemented`, and conformance fixture 064 (three cases: the §9.7 instance and §11.7 branch sites plus an uncategorized cause) passes.
18+
- **Observer privacy flag `disable_llm_payload` renamed to `disable_provider_payload`** (proposal 0059, observability §5.5.4, spec v0.54.0). The observer-level flag on both bundled observers (`OTelObserver` and `LangfuseObserver`) is renamed, and its scope broadens from LLM-completion payload to any provider-call payload (LLM completion today; embedding and rerank when those land). This is a breaking change to both observer constructors: config passing `disable_llm_payload=True` (or `False`) updates to `disable_provider_payload=...` with no other change. The default stays `True` (payload suppressed), and the gating behavior for `LlmCompletionEvent` / `LlmFailedEvent` rendering is unchanged at every existing site. The rename is the only part of proposal 0059 adopted this cycle: the retrieval-provider capability itself (the `EmbeddingProvider` protocol, the `EmbeddingEvent` / `EmbeddingFailedEvent` typed variants, and the embedding span / observation mapping) is not yet implemented and rides as `not-yet` in `conformance.toml`. The §5.5.4 rename touches existing LLM-payload gating, so it lands with the pin.
19+
- **Pinned spec advances v0.53.0 → v0.55.1 across the v0.14.0 cycle**, in two steps: v0.54.0 (proposal 0059, the observer-flag rename above) and v0.55.1 (proposal 0065 above; the v0.55.1 patch also carries an observability §11 span-links text reconciliation that narrows an *Out of scope* bullet, with no python-observable change). `conformance.toml` records 0065 as `implemented` and 0059 as `not-yet` (only its cross-spec flag rename was adopted).
1920

2021
### Fixed
2122

conformance.toml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
[manifest]
3434
implementation = "openarmature-python"
35-
spec_pin = "v0.54.0"
35+
spec_pin = "v0.55.1"
3636

3737
# Status values:
3838
# implemented — shipped behavior matches the proposal's contract
@@ -605,3 +605,19 @@ since = "0.13.0"
605605
# the pin even though the embedding capability does not).
606606
[proposals."0059"]
607607
status = "not-yet"
608+
609+
# Spec v0.55.0 (proposal 0065; repo pins v0.55.1). Failure-isolation
610+
# cause fidelity at non-node placements (pipeline-utilities §6.3 /
611+
# §11.7). At instance (§9.7), branch (§11.7), and parent-node
612+
# middleware sites the engine wraps the originating error as a §4
613+
# ``node_exception`` carrier before isolation catches it;
614+
# ``FailureIsolatedEvent.caught_exception.category`` now resolves
615+
# THROUGH that carrier to the originating cause instead of reporting the
616+
# masking ``node_exception``. Fixture 064 (three cases) passes;
617+
# node-level placement (fixture 061) was already faithful. The pin is
618+
# v0.55.1 rather than v0.55.0 because v0.55.1 adds an observability §11
619+
# span-links text reconciliation (no proposal, no python-observable
620+
# change).
621+
[proposals."0065"]
622+
status = "implemented"
623+
since = "0.14.0"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Specification = "https://github.com/LunarCommand/openarmature-spec"
6363
openarmature = "openarmature.cli:main"
6464

6565
[tool.openarmature]
66-
spec_version = "0.54.0"
66+
spec_version = "0.55.1"
6767

6868
[dependency-groups]
6969
dev = [

src/openarmature/AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# OpenArmature — Agent documentation
22

3-
*This is the agent guide bundled with the openarmature Python package, version 0.13.0 (spec v0.54.0). For the full docs site see [openarmature.ai](https://openarmature.ai). For the canonical spec text see [openarmature.org/capabilities](https://openarmature.org/capabilities/). For project-specific conventions for the code you're editing, see the host project's `AGENTS.md` or `CLAUDE.md`.*
3+
*This is the agent guide bundled with the openarmature Python package, version 0.13.0 (spec v0.55.1). For the full docs site see [openarmature.ai](https://openarmature.ai). For the canonical spec text see [openarmature.org/capabilities](https://openarmature.org/capabilities/). For project-specific conventions for the code you're editing, see the host project's `AGENTS.md` or `CLAUDE.md`.*
44

55
## TL;DR
66

@@ -10,7 +10,7 @@ OpenArmature is a workflow framework for LLM pipelines and tool-calling agents:
1010

1111
## Capability contracts
1212

13-
_Sourced from openarmature-spec v0.54.0. Each entry below reproduces §1 (Purpose) and §2 (Concepts) of the capability's `spec.md` verbatim — including additions from accepted proposals that this Python implementation may not yet ship. For per-proposal implementation status (implemented / partial / textual-only / not-yet), see the `conformance.toml` manifest at the repo root. For the full spec text (execution model, error semantics, determinism, observer hooks, etc.) see the linked docs site._
13+
_Sourced from openarmature-spec v0.55.1. Each entry below reproduces §1 (Purpose) and §2 (Concepts) of the capability's `spec.md` verbatim — including additions from accepted proposals that this Python implementation may not yet ship. For per-proposal implementation status (implemented / partial / textual-only / not-yet), see the `conformance.toml` manifest at the repo root. For the full spec text (execution model, error semantics, determinism, observer hooks, etc.) see the linked docs site._
1414

1515
### Capability: `graph-engine`
1616

src/openarmature/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"""
2626

2727
__version__ = "0.13.0"
28-
__spec_version__ = "0.54.0"
28+
__spec_version__ = "0.55.1"
2929
# Proposal 0052 (spec observability §5.1 / §8.4.1): canonical
3030
# package-registry name for this implementation. Surfaces on every
3131
# OTel invocation span as ``openarmature.implementation.name`` and on

tests/conformance/harness/fixtures.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,21 @@ class CasesFixture(_ForbidExtras):
165165
166166
Used by ``007-compile-errors``, the checkpointing fixtures (024–031),
167167
and the determinism / multi-run observability fixtures. Optional shared
168-
``subgraph`` / ``subgraph_with_idx`` at the top level apply across all
169-
cases. Any other top-level key not listed here is rejected.
168+
``subgraph`` / ``subgraph_with_idx`` / ``subgraphs`` at the top level
169+
apply across all cases. Any other top-level key not listed here is
170+
rejected.
170171
"""
171172

172173
cases: list[CaseSpec]
173-
# Shared graph-shape blocks that apply across every case. Empirically
174-
# only `subgraph` and `subgraph_with_idx` appear at the top level of
175-
# cases-fixtures; the plural `subgraphs` form has not been seen at
176-
# the cases-fixture top level.
174+
# Shared graph-shape blocks that apply across every case. The singular
175+
# `subgraph` / `subgraph_with_idx` and the plural `subgraphs` map
176+
# (name -> graph-spec, as the parallel-branches fixtures use) may all
177+
# appear at the cases-fixture top level. Fixture 064 (failure-isolation
178+
# cause fidelity) is the first to share a plural `subgraphs:` across
179+
# cases.
177180
subgraph: SubgraphDefinition | None = None
178181
subgraph_with_idx: SubgraphDefinition | None = None
182+
subgraphs: dict[str, SubgraphDefinition] | None = None
179183

180184

181185
# ---------------------------------------------------------------------------

tests/conformance/test_pipeline_utilities.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,14 @@ def _load(path: Path) -> dict[str, Any]:
8383
# the `cases:` shape carries seeded-record + migrations + resume blocks.
8484
_LAST_DRIVEN_FIXTURE = 38
8585

86-
# Failure-isolation fixtures (058-063, proposal 0050 §6.3) are middleware
87-
# fixtures this runner handles. They sit past _LAST_DRIVEN_FIXTURE only
88-
# because the 039-057 range (state migration / checkpoint fan-out) is owned
89-
# by dedicated runners (test_state_migration.py / test_checkpoint.py), not
90-
# because this runner can't drive them. Fixture 064 (cause fidelity) joins
91-
# when the spec pin advances to v0.55.0.
92-
_FAILURE_ISOLATION_FIXTURES = frozenset(range(58, 64))
86+
# Failure-isolation fixtures (058-064, proposals 0050 §6.3 + 0065) are
87+
# middleware fixtures this runner handles. They sit past _LAST_DRIVEN_FIXTURE
88+
# only because the 039-057 range (state migration / checkpoint fan-out) is
89+
# owned by dedicated runners (test_state_migration.py / test_checkpoint.py),
90+
# not because this runner can't drive them. Fixture 064 (cause fidelity at
91+
# non-node placements, proposal 0065) joined when the spec pin advanced to
92+
# v0.55.1.
93+
_FAILURE_ISOLATION_FIXTURES = frozenset(range(58, 65))
9394

9495

9596
def _fixture_paths() -> list[Path]:
@@ -488,13 +489,18 @@ async def test_pipeline_utility_fixture(
488489
pytest.skip(f"{fixture_id}: {_DEFERRED_FIXTURES[fixture_id]}")
489490
spec = _load(fixture_path)
490491

491-
# Cases-shape fixtures (014, 016, 018-019, 021-023): each case is
492-
# a self-contained graph + middleware + expected block. The outer
492+
# Cases-shape fixtures (014, 016, 018-019, 021-023, 064): each case
493+
# is a self-contained graph + middleware + expected block. The outer
493494
# fixture may define shared ``subgraph:`` / ``subgraph_with_idx:``
494-
# blocks that every case references; merge them into each case
495-
# before dispatching so the case sees them as if they were its own.
495+
# (singular) or ``subgraphs:`` (plural, name -> graph-spec, as the
496+
# parallel-branches fixtures use) blocks that every case references;
497+
# merge them into each case before dispatching so the case sees them
498+
# as if they were its own. ``setdefault`` below preserves any block a
499+
# case defines for itself.
496500
if "cases" in spec:
497-
shared_subgraph_blocks = {k: spec[k] for k in ("subgraph", "subgraph_with_idx") if k in spec}
501+
shared_subgraph_blocks = {
502+
k: spec[k] for k in ("subgraph", "subgraph_with_idx", "subgraphs") if k in spec
503+
}
498504
for case in spec["cases"]:
499505
case_name = case.get("name", "<unnamed>")
500506
merged: dict[str, Any] = dict(case)

tests/test_smoke.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
def test_package_versions() -> None:
1111
assert openarmature.__version__ == "0.13.0"
12-
assert openarmature.__spec_version__ == "0.54.0"
12+
assert openarmature.__spec_version__ == "0.55.1"
1313

1414

1515
def test_spec_version_matches_pyproject() -> None:

0 commit comments

Comments
 (0)