## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Catalog and package skeleton - [ ] 1.1 Add `@opentelemetry/sdk-node`, `@opentelemetry/sdk-trace-node`, and `@opentelemetry/exporter-trace-otlp-http` to root `package.json` `catalogs.observability` (skip any already pinned by `@suaveplan/opentelemetry`). - [ ] 1.2 Create `packages/testing/testing-integration-otel-collector/` with `package.json` (version `0.1.0`, `type: "module"`, `sideEffects: false`, `workspace:^` dep on `@suaveplan/testing-integration`, catalog dep on `testcontainers`). - [ ] 1.3 Add `tsconfig.lib.json` extending `@suaveplan/typescript-config/library-node.json`; add `vite.config.ts` with `preserveModules: true`; add `vitest.config.ts` via `createTestConfig()`. - [ ] 1.4 Stub `README.md` (one-paragraph description, install, quick start, **Modules** index linking each co-located `.md`). ## 2. ServiceFixture implementation - [ ] 2.1 Implement `src/fixture/otel-collector-fixture.ts` — `OtelCollectorFixture` implementing `ServiceFixture`; constructor accepts injectable `containerFactory` and `fetchFn`. - [ ] 2.2 Implement `src/config/synthesize-config.ts` — produce `otelcol-config.yaml` from `{ receivers, exporters }`; include the in-memory exporter wiring when `'memory'` is requested. - [ ] 2.3 Implement `src/health/health-check.ts` — HTTP GET on `:13133/health/status`, default timeout 60 s, retries via `HealthPoller` from `@suaveplan/testing-integration`. - [ ] 2.4 Implement `src/env-bridge/env-bridge.ts` — sets `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_PROTOCOL`, optional `OTEL_EXPORTER_OTLP_HEADERS`; restores prior values on teardown. - [ ] 2.5 Implement `src/query/get-spans.ts` — `getSpans({ filter })` queries the memory exporter via the collector's debug HTTP endpoint; returns `ReadableSpan[]`; throws `IntegrationError("INTEGRATION.OTEL_COLLECTOR.MEMORY_EXPORTER_NOT_CONFIGURED", …)` when the memory exporter is not in the active config. - [ ] 2.6 Implement `src/errors/codes.ts` — string-literal-union of every `INTEGRATION.OTEL_COLLECTOR.` code thrown by the package. - [ ] 2.7 Co-locate `*.test.ts`, `*.schemas.ts`, `*.md` for every implementation file (`.md` ≥ 200 words with simple + advanced examples per `openspec/AGENTS.md` §4). ## 3. Image pinning (tracked, follow-up) - [ ] 3.1 Tag-pin `otel/opentelemetry-collector-contrib:0.` initially. - [ ] 3.2 Open a tracking task to migrate to digest-pin (`@sha256:…`) once the minor version is locked — referenced from audit §5 "Images pinned by tag, not digest". ## 4. Runner reporter — `@suaveplan/testing/reporters/otel` - [ ] 4.1 Add subpath export `./reporters/otel` to `packages/testing/testing/package.json`. - [ ] 4.2 Implement `src/reporters/otel/vitest-reporter.ts` — Vitest reporter that opens a span per `it`/`test`, records `exception.*` events on assertion failure, and writes the full span tree to `playwright-report/traces/.json` on red. - [ ] 4.3 Implement `src/reporters/otel/bun-test-reporter.ts` — equivalent for bun-test (uses bun-test's reporter API). - [ ] 4.4 Implement `src/reporters/otel/trace-sink.ts` — uploads the failure trace to `TESTING_TRACE_SINK_URL` (Garage S3 PUT); best-effort (failures logged, not thrown). - [ ] 4.5 Implement `src/reporters/otel/fixture-events.ts` — hook into `FixtureManager` lifecycle to emit `setup-start`/`setup-end`/`teardown-start`/`teardown-end` span events. - [ ] 4.6 Co-locate tests, schemas, and docs for every new file. ## 5. Spec deltas - [ ] 5.1 Land `specs/testing-integration-otel-collector/spec.md` with all `## ADDED Requirements` (image policy, env-bridge, health-check, config shape, span-query, errors). - [ ] 5.2 Land `specs/testing/spec.md` with the `## ADDED Requirements` block carrying the **Test-execution OTel export** requirement. - [ ] 5.3 On ship, fold both into `openspec/specs/testing-integration-otel-collector/spec.md` (new file) and `openspec/specs/testing/spec.md` (append). ## 6. Verification - [ ] 6.1 `bunx turbo lint typecheck test --filter=@suaveplan/testing-integration-otel-collector` green. - [ ] 6.2 `bunx turbo test:coverage --filter=@suaveplan/testing-integration-otel-collector` at 100% statement / branch / function / line. - [ ] 6.3 `bunx turbo lint typecheck test --filter=@suaveplan/testing` green after reporter additions; coverage stays at 100%. - [ ] 6.4 End-to-end smoke: a sample test suite with `OTEL_EXPORTER_OTLP_ENDPOINT` set produces queryable spans via `getSpans()`. - [ ] 6.5 Banned-pattern scan (`@deprecated`, `TODO`, `FIXME`, `ts-ignore`, `ts-expect-error`, `.skip`, `.only`, bare `any`) clean. ## 7. Archive - [ ] 7.1 Move `openspec/changes/enterprise-testing-integration-otel-collector/` → `openspec/archive/-enterprise-testing-integration-otel-collector/` after all gates pass.