Skip to content

Implement fan-out degrade contribution (proposal 0066)#161

Merged
chris-colinsky merged 1 commit into
mainfrom
feature/0066-fan-out-degrade-contribution
Jun 15, 2026
Merged

Implement fan-out degrade contribution (proposal 0066)#161
chris-colinsky merged 1 commit into
mainfrom
feature/0066-fan-out-degrade-contribution

Conversation

@chris-colinsky

Copy link
Copy Markdown
Member

Summary

Adopts proposal 0066 (spec v0.56.0): a degraded fan-out instance is a success whose contribution is its degraded_update, read in subgraph-field-name space. The submodule advances v0.55.1 to v0.56.0 and conformance.toml marks 0066 implemented.

Engine

  • extra_outputs keying fix. The per-instance partial is now uniformly subgraph-keyed across _extract_instance_partial, the accumulator, _rolled_forward_partial (resume), and both _fan_in_* functions, so a degrade's subgraph-space degraded_update composes through the same fan-in. This fixes a latent bug: an instance degraded_update's extra_outputs values were looked up by the parent field name and silently dropped (collect_field was unaffected, which is why fixture 064 with no extra_outputs didn't surface it).
  • Compile-time check. A static degraded_update on a fan-out instance FailureIsolationMiddleware that omits collect_field now raises FanOutDegradedUpdateMissingCollectField. A callable degraded_update is exempt (its output isn't knowable at construction).
  • Null slot. A callable degraded_update that omits collect_field yields a graceful null slot (the fan-in reads via .get), never a degrade-time raise; the positional collection slot is preserved.

Harness

Fixture 065-fan-out-failure-isolation-degrade-contribution (four cases) is wired into the pipeline-utilities runner: the runner gained expected_compile_error handling for a cases-shape graph: block, and the adapter gained the any fixture type for Case 3's list<any> null-slot collection.

Scope

Success-path and resume behavior for correctly-configured fan-outs is unchanged; the existing fan-out and checkpoint fixtures stay green. The parallel-branches counterpart (Case 4) was already correct from the prior parallel-branches fix and is now pinned by fixture 065.

Validation

  • uv run pytest tests/: 1301 passed, 376 skipped
  • uv run pytest "tests/conformance/" -k 065: four cases pass
  • uv run ruff check ., uv run pyright: clean
  • uv run python scripts/check_conformance_manifest.py: 61/61
  • uv run mkdocs build: clean

Adopt proposal 0066: a degraded fan-out instance is a success whose
contribution is its degraded_update, read in subgraph-field-name space.

Make the per-instance partial uniformly subgraph-keyed across the
extract, accumulator, resume, and fan-in paths, so a degrade's
subgraph-space degraded_update composes through the same fan-in. This
fixes a latent bug where an instance degraded_update's extra_outputs
values were looked up by parent field name and silently dropped.

A static degraded_update on an instance FailureIsolationMiddleware that
omits collect_field is now a compile-time error
(FanOutDegradedUpdateMissingCollectField); a callable degraded_update
that omits it yields a graceful null slot rather than raising.

Advance the pinned spec to v0.56.0, mark 0066 implemented, wire fixture
065 (four cases), and sync the spec-version declarations.
Copilot AI review requested due to automatic review settings June 15, 2026 18:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements openarmature-spec proposal 0066 (spec v0.56.0) by updating fan-out failure-isolation degrade semantics so a degraded instance is treated as a success whose contribution is its degraded_update in subgraph-field-name space, and updates the conformance harness + pins to v0.56.0.

Changes:

  • Fix fan-out extra_outputs handling to consistently read per-instance partials in subgraph space and project into parent fields during fan-in (including resume/rolled-forward paths).
  • Add a compile-time validation error (FanOutDegradedUpdateMissingCollectField) for static per-instance degraded_update mappings that omit collect_field.
  • Extend conformance runner/type adapter to support fixture 065 patterns (expected_compile_error, any type), and bump spec version pins/docs.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/test_smoke.py Updates spec version assertion to v0.56.0.
tests/conformance/test_pipeline_utilities.py Adds compile-error case handling and includes fixture 065 in the driven set.
tests/conformance/adapter.py Adds any fixture type support for null-slot collection cases.
src/openarmature/graph/fan_out.py Aligns per-instance partials and fan-in/out logic with proposal 0066 (subgraph-space partials, .get for null slots).
src/openarmature/graph/errors.py Introduces FanOutDegradedUpdateMissingCollectField compile error category.
src/openarmature/graph/builder.py Adds compile-time check for static degraded_update missing collect_field.
src/openarmature/graph/init.py Re-exports the new compile error in the public API.
src/openarmature/AGENTS.md Updates referenced spec version to v0.56.0.
src/openarmature/init.py Bumps __spec_version__ to v0.56.0.
pyproject.toml Bumps [tool.openarmature].spec_version to v0.56.0.
conformance.toml Pins spec to v0.56.0 and marks proposal 0066 as implemented.
CHANGELOG.md Documents proposal 0066 behavior and the spec pin bump to v0.56.0.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chris-colinsky chris-colinsky merged commit 2c2ba1f into main Jun 15, 2026
7 checks passed
@chris-colinsky chris-colinsky deleted the feature/0066-fan-out-degrade-contribution branch June 15, 2026 18:59
chris-colinsky added a commit that referenced this pull request Jun 18, 2026
The fan-out-with-retry degrade mode supplied its extra_outputs value
under the parent field name (`topics`) in degraded_update, but
proposal 0066 reads degraded_update in the subgraph's field-name space.
The subgraph field is `topic` (extra_outputs={topics: topic}), so the
parent-keyed entry was ignored, leaving the slot null (0069) and
tripping BatchState.topics: list[str] validation in degrade mode.

Key the degraded value by the subgraph field `topic` (the doc
walkthrough already documents `topic: other`). Caught running
MODE=degrade against the v0.14.0rc1 artifact; the example smoke test
only exercises fail_fast, so it slipped through #161.
chris-colinsky added a commit that referenced this pull request Jun 18, 2026
* chore(release): v0.14.0

Real release of v0.14.0 (retry & reliability; pinned spec v0.53.0 ->
v0.60.0). Bump the package version from 0.14.0rc1 to 0.14.0 across
pyproject, __version__, test_smoke, and the lockfile; regenerate the
bundled AGENTS.md version stamp. The CHANGELOG [0.14.0] section is
already dated 2026-06-17 (no drift). Tagging v0.14.0 publishes to PyPI
and creates the GitHub Release.

rc1 verified on TestPyPI (install, version, [otel] import, hello-world
against a live LLM).

* Fix degrade extra-outputs key in fan-out example

The fan-out-with-retry degrade mode supplied its extra_outputs value
under the parent field name (`topics`) in degraded_update, but
proposal 0066 reads degraded_update in the subgraph's field-name space.
The subgraph field is `topic` (extra_outputs={topics: topic}), so the
parent-keyed entry was ignored, leaving the slot null (0069) and
tripping BatchState.topics: list[str] validation in degrade mode.

Key the degraded value by the subgraph field `topic` (the doc
walkthrough already documents `topic: other`). Caught running
MODE=degrade against the v0.14.0rc1 artifact; the example smoke test
only exercises fail_fast, so it slipped through #161.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants