Skip to content

Add failure-isolation catch gate and cause-chain classification primitive (0074)#174

Merged
chris-colinsky merged 5 commits into
mainfrom
feature/0074-failure-isolation-catch
Jun 20, 2026
Merged

Add failure-isolation catch gate and cause-chain classification primitive (0074)#174
chris-colinsky merged 5 commits into
mainfrom
feature/0074-failure-isolation-catch

Conversation

@chris-colinsky

Copy link
Copy Markdown
Member

Summary

Implements proposal 0074 (spec v0.65.0): the failure-isolation catch cause-chain category gate (§6.3) and the public cause-chain classification primitive (§6.4), plus the §6.1 retry-classifier-depth documentation. Pins the spec submodule v0.64.0 -> v0.65.0.

What changed

  • catch gate (§6.3). FailureIsolationMiddleware gains an optional catch: a set of error categories. An exception is caught only if the derived category of its cause chain (the outermost non-carrier link's category, resolved through the engine's node_exception carriers, the same value reported as caught_exception.category) is in the set. This closes a degrade-into-crash footgun: at a wrapping placement (subgraph, fan-out instance, branch) the engine wraps the originating failure in a carrier, so a predicate inspecting the surface exception sees only the carrier and misses it, whereas catch classifies through it. catch composes with predicate as a conjunction (catch checked first, short-circuiting); both default permissive, so the both-unset default stays catch-all, and a null derived category never matches a non-empty set.
  • §6.4 classification primitive. The carrier-skipping walk behind catch and caught_exception is promoted to a public classify_cause_chain(exc) -> CaughtException. The cause-chain types (CauseLink, CaughtException) move into a new graph/cause_chain.py alongside the primitive, so the concept has one cohesive home and events consumes it; the public openarmature.graph.* import paths are unchanged via the re-export.
  • §6.1 (docs only). The default retry classifier's single-level depth is documented as deliberate (it classifies at re-attempt granularity, distinct from §6.3's full-chain degrade); no behavior change.
  • Not shipped: the optional native-exception-type catch form (spec MAY); the normative contract is the category set.

Testing

  • Conformance fixture 072 (two cases: catch matches through an instance-placement carrier and degrades; a non-matching catch propagates with no event).
  • Unit tests: catch matches-through-carrier / non-match / null-category / conjunction / unset / short-circuit, and the primitive directly.
  • Full suite green (1357 passed); pyright, ruff, and mkdocs clean.

Notes

  • The 0.15.0 changelog date is tentative pending the release tag.

Advance the spec submodule pin v0.64.0 -> v0.65.0 for accepted proposal
0074 (failure-isolation catch gate + §6.4 cause-chain classification
primitive). Updates __spec_version__, the pyproject spec_version, the
smoke assertion, the conformance.toml spec_pin, and regenerates the
bundled AGENTS.md. conformance.toml records 0074 as implemented.
FailureIsolationMiddleware gains an optional `catch` set of error
categories: an exception is caught only if the derived category of its
cause chain (resolved through node_exception carriers) is in the set,
conjoined with `predicate` (catch checked first, short-circuiting).

The carrier-skipping walk behind `catch` and `caught_exception` becomes
a public primitive, classify_cause_chain(exc) -> CaughtException. The
cause-chain types (CauseLink, CaughtException) move into the new
cause_chain module alongside it, so the concept has one home and events
consumes it; the public openarmature.graph paths are unchanged. The
default retry classifier's single-level depth is documented as
deliberate (no behavior change). Unit tests cover the gate, the
short-circuit, and the primitive.
Parse the `catch` directive on the failure_isolation fixture middleware
config and add fixture 072 to the failure-isolation fixture set. 072
(two cases) drives the catch gate matching through a §9.7 instance
node_exception carrier (degrade) and a non-matching catch (propagate).
Document the `catch` category gate and the public classify_cause_chain
primitive in the middleware concepts page, and add the 0.15.0 changelog
entry (advancing the spec-pin bullet to v0.65.0).
Copilot AI review requested due to automatic review settings June 20, 2026 16:43

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 spec proposal 0074 (spec v0.65.0) by adding a failure-isolation catch category gate and promoting the carrier-skipping cause-chain walk to a public classify_cause_chain primitive, plus related documentation and spec pin/version updates.

Changes:

  • Add catch (category-set gate) to FailureIsolationMiddleware, using cause-chain derived category to match through node_exception carriers.
  • Introduce graph/cause_chain.py with CauseLink, CaughtException, and classify_cause_chain, and re-export via openarmature.graph.
  • Bump spec pin/version to v0.65.0 and update docs, changelog, and conformance runner for fixture 072.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/unit/test_failure_isolation_middleware.py Adds unit tests for catch gating behavior and classify_cause_chain.
tests/test_smoke.py Updates __spec_version__ assertion to 0.65.0.
tests/conformance/test_pipeline_utilities.py Adds fixture 072 and wires catch from conformance configs.
src/openarmature/graph/middleware/retry.py Documents deliberate single-level retry classification depth.
src/openarmature/graph/middleware/failure_isolation.py Implements catch gate and uses classify_cause_chain for gating + event payload.
src/openarmature/graph/events.py Moves CaughtException type usage to new cause-chain module import.
src/openarmature/graph/cause_chain.py New public cause-chain types + classification primitive.
src/openarmature/graph/init.py Re-exports cause-chain types/primitive from openarmature.graph.
src/openarmature/AGENTS.md Updates bundled agent guide spec version to v0.65.0.
src/openarmature/init.py Updates __spec_version__ to 0.65.0.
pyproject.toml Updates tool.openarmature.spec_version to 0.65.0.
docs/concepts/middleware.md Documents catch gate and the new classify_cause_chain primitive.
conformance.toml Pins spec to v0.65.0 and records proposal 0074 as implemented.
CHANGELOG.md Adds entry for proposal 0074 and updates spec pin narrative.
Comments suppressed due to low confidence (1)

src/openarmature/graph/events.py:782

  • openarmature.graph.events previously exported CaughtException / CauseLink (via __all__). Removing them is an observable API change; consider continuing to re-export them from this module for backward compatibility (even if the canonical home moved to cause_chain).
__all__ = [
    "FailureIsolatedEvent",
    "FanOutEventConfig",
    "InvocationCompletedEvent",
    "InvocationStartedEvent",
    "LlmCompletionEvent",
    "LlmFailedEvent",
    "LlmRetryAttemptEvent",
    "MetadataAugmentationEvent",
    "NodeEvent",
    "ParallelBranchesEventConfig",
]

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

Comment thread src/openarmature/graph/middleware/failure_isolation.py
Comment thread src/openarmature/graph/middleware/failure_isolation.py
Comment thread src/openarmature/graph/middleware/failure_isolation.py
Comment thread src/openarmature/graph/events.py
Comment thread docs/concepts/middleware.md
Comment thread docs/concepts/middleware.md
PR #174 review: reject a bare str for FailureIsolationMiddleware.catch
(a str is a Collection[str], so it would substring-match and silently
mis-gate) and normalize to a frozenset. Tighten the derived-category
wording in the docstring, the concepts page, and the classify example
to the outermost non-carrier link with a category (an uncategorized
surface link resolves to the deeper categorized cause). Fix the stale
events/errors import comment now that cause_chain imports only errors.
@chris-colinsky chris-colinsky merged commit d803356 into main Jun 20, 2026
6 checks passed
@chris-colinsky chris-colinsky deleted the feature/0074-failure-isolation-catch branch June 20, 2026 17:20
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