diff --git a/conformance.toml b/conformance.toml index f2579142..611699e1 100644 --- a/conformance.toml +++ b/conformance.toml @@ -846,10 +846,12 @@ note = "The SAVE-side enclosing_fan_out_lineage keying (pipeline-utilities §10. status = "not-yet" # Spec v0.82.0 (proposal 0087). Conformance-adapter within-node -# directive execution order (§8.3). Not-yet; observability fixture 135 -# defers with it. +# directive execution order (§8.3). Implemented since 0.17.0; +# observability fixture 135 pins it. [proposals."0087"] -status = "not-yet" +status = "implemented" +since = "0.17.0" +note = "Within-node directive execution order (conformance-adapter §8.3): a node's sibling directives execute in fixture-document order (mapping insertion order, not sorted-by-key). Python was already conformant -- the fixture loader uses yaml.safe_load, which preserves mapping insertion order, and the hand-built metadata driver (_apply_metadata_directives) iterates a node's directives in key order, so fixtures 043 / 045 (augment-then-capture vs capture-then-augment) already passed. This proposal ratifies that rule; the dedicated pin fixture observability/135 (the SAME two order-sensitive directives -- augment_metadata write + capture_invocation_metadata_into read -- in opposite document order across two cases, the captured snapshot diverging) is un-deferred and wired onto the existing metadata driver. No src change: the order-preserving load + key-order execution already satisfy §8.3, and a loader guard-comment pins the safe_load dependence per §8.2." # Spec v0.83.0 (proposal 0088). Langfuse parallel-branches mapping # parity (observability §8.4.8). Not-yet; observability fixture 136 diff --git a/tests/conformance/harness/loader.py b/tests/conformance/harness/loader.py index fa2def43..0e1b3c99 100644 --- a/tests/conformance/harness/loader.py +++ b/tests/conformance/harness/loader.py @@ -68,6 +68,11 @@ def load_fixture(path: Path) -> Fixture: directives we haven't modelled yet. """ with path.open() as f: + # yaml.safe_load preserves mapping insertion (document) order in + # Python, so a node's sibling directives keep their fixture order. + # Conformance-adapter §8.3 (proposal 0087) requires directives to + # execute in document order, and observability/135 pins the + # divergence -- do not swap in an order-losing loader. raw = yaml.safe_load(f) return _FIXTURE_ADAPTER.validate_python(raw) diff --git a/tests/conformance/test_observability.py b/tests/conformance/test_observability.py index bea8d2e3..fbd27e07 100644 --- a/tests/conformance/test_observability.py +++ b/tests/conformance/test_observability.py @@ -100,6 +100,14 @@ def _reset_otel_global_tracer_provider(restore_to: object) -> None: "044-get-invocation-metadata-fan-out-scoping", "045-get-invocation-metadata-retry-scoping", "046-get-invocation-metadata-outside-invocation", + # proposal 0087 (within-node directive execution order, spec + # v0.82.0). 135 places augment_metadata + capture_invocation_ + # metadata_into in opposite document order across two cases; the + # captured snapshot diverges only if a node's sibling directives + # run in fixture order. Reuses the 043/045 metadata driver, which + # iterates node directives in key order -- see + # _apply_metadata_directives. + "135-within-node-directive-execution-order", "001-otel-basic-trace", "002-otel-subgraph-hierarchy", "003-otel-error-status", @@ -384,12 +392,6 @@ def _reset_otel_global_tracer_provider(restore_to: object) -> None: "134-langfuse-nested-fan-out-parent-resolution", ) }, - # Proposal 0087 (within-node directive execution order, spec v0.82.0). - # The conformance-adapter document-order directive rule is unimplemented - # until a later v0.16.0 PR. - "135-within-node-directive-execution-order": ( - "within-node directive execution order (proposal 0087) not-yet implemented" - ), # Proposal 0088 (Langfuse parallel-branches mapping parity, spec # v0.83.0). The §8.4.8 per-branch dispatch-span Langfuse observation is # unimplemented until a later v0.16.0 PR. @@ -735,6 +737,7 @@ async def test_observability_fixture(fixture_path: Path) -> None: "044-get-invocation-metadata-fan-out-scoping", "045-get-invocation-metadata-retry-scoping", "046-get-invocation-metadata-outside-invocation", + "135-within-node-directive-execution-order", }: await _run_get_invocation_metadata_fixture(spec) else: