## Why Section 4 of the test-suite audit (`/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md`) flags that observability of the test suite itself is absent: every `@suaveplan/*` package ships OTel instrumentation via `@opentelemetry/api`, but there is no fixture that exercises the export path end-to-end and no runner hook that turns each `it`/`test` into a span. Today CI can only assert "no SDK registered = no-op"; there is no way to verify that a counter, histogram, or span actually reaches a collector when one is registered. Section 1 of the same audit lists the OpenTelemetry collector as a critical missing service-fixture (alongside OIDC, Mongo, Kafka/NATS). This change closes both gaps in a single capability: a `@suaveplan/testing-integration-otel-collector` plugin (a `ServiceFixture` for `otel/opentelemetry-collector-contrib`) plus a normative requirement on the `testing` capability that the runner SHALL emit a span per test, an event per assertion failure, and an event per fixture lifecycle transition when an OTLP endpoint is configured. Failed-test span trees are serialised to `playwright-report/traces/` and uploaded to a configured Garage S3 sink — directly addressing audit §4 ("Trace-on-failure exists locally but is not exported anywhere"). ## What Changes ### New plugin package — `@suaveplan/testing-integration-otel-collector` - Lives at `packages/testing/testing-integration-otel-collector` (mirrors the `testing-integration-*` plugin convention from `CLAUDE.md`). - Implements the `ServiceFixture` interface from `@suaveplan/testing-integration` with image `otel/opentelemetry-collector-contrib` pinned to a specific minor (digest-pin tracked in `tasks.md`). - Env-bridge: `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_PROTOCOL` (`http/protobuf` default, `grpc` opt-in), optional `OTEL_EXPORTER_OTLP_HEADERS`. - HTTP healthcheck on `:13133/health/status` (port configurable; default timeout 60 s). - Config object `{ receivers: ('otlp-grpc' | 'otlp-http')[]; exporters: ('logging' | 'memory' | 'jaeger' | 'file')[]; configFile?: string }` — when no `configFile` is provided the plugin synthesises a minimal `otelcol-config.yaml` from the receivers/exporters lists. - Public helper `getSpans({ filter })` queries the in-memory exporter (when configured) and returns `ReadableSpan[]` for assertion in tests. - Errors prefixed `INTEGRATION.OTEL_COLLECTOR.*`; injectable `containerFactory` and `fetchFn` for unit-testability of the fixture itself. ### Test-execution OTel export — addition to the `testing` capability When `OTEL_EXPORTER_OTLP_ENDPOINT` is set the test runner SHALL emit one span per `it`/`test` (`name`, `status`, `attributes={ suite, file, retry }`), one event per assertion failure (`exception.type`, `exception.message`, `exception.stacktrace`), and one event per fixture lifecycle transition (`setup-start`, `setup-end`, `teardown-start`, `teardown-end`). Implementation hooks ship at `@suaveplan/testing/reporters/otel` for both vitest and bun-test. Failed tests serialise their full span tree to `playwright-report/traces/.json` and (when `TESTING_TRACE_SINK_URL` is set) upload that file to the configured Garage S3 bucket. ## Capabilities ### New Capabilities - `testing-integration-otel-collector` — a `ServiceFixture` for the OpenTelemetry collector (image policy, env-bridge, health-check contract, config shape, span-query helper, error code prefix). ### Modified Capabilities - `testing` — adds the **Test-execution OTel export** requirement (runner emits spans/events for tests and fixture lifecycle, trace-on-failure serialised and uploaded). ## Impact - **Affected code:** new package at `/mnt/s/web/genesis/packages/testing/testing-integration-otel-collector/**`; new reporters at `/mnt/s/web/genesis/packages/testing/testing/src/reporters/otel/**`. - **Affected consumers:** every `@suaveplan/*` test suite gains span export when the env var is set; zero behaviour change when unset. - **Catalog additions (root `package.json`):** none — `@opentelemetry/sdk-node`, `@opentelemetry/sdk-trace-node`, and `@opentelemetry/exporter-trace-otlp-http` are added under `catalogs.observability` only if not already pinned by `@suaveplan/opentelemetry`. - **Pre-publish gate:** plugin package must hit 100% Istanbul coverage (per `openspec/AGENTS.md` §7) and pass the standard `lint typecheck test` suite before publish. - **Cross-cutting:** the `testing` spec gains a new requirement; folding on archive will append it to `openspec/specs/testing/spec.md`.