Description
cf2otel.scrape.errors counts failures but not why, so rate limiting, auth, entitlement, timeout and schema errors look the same on a dashboard.
Acceptance Criteria
- #1 Collector error metrics carry a bounded error class attribute (rate_limited, auth, unentitled, timeout, schema, other)
- #2 Every new signal and attribute is declared in internal/semconv, listed in docs/signals.md, and has a panel in grafana/build_dashboard.py
Definition of Done
- #1 just check (fmt-check, lint, vet, test, tidy-check, build, vuln)
- #2 just ci before a change that touches the Dockerfile, goreleaser or the image (adds snapshot + image)
- #3 Every new signal or attribute name declared in internal/semconv and listed in docs/signals.md
Implementation Plan
Loop15 E51C: typed bounded error classification at collector scrape boundary, registered public-path red witness, no message-text classification where typed evidence exists; local gate and CodeRabbit then independent review and root landing. Dashboard and live evidence remain root-owned.
Implementation Notes
Loop16 RECON-M1 checked source criteria 1 against landed tests at ced4edfbfb66f1b9ee45037bdb425b69820a8ebe. Evidence: codex/evidence-loop16/RECON-return.txt. No new live or browser observation is claimed.
Loop16 DASH-1 exact reviewed panel keeps bounded error class and independent exporter instances. Source landed at d997015 after assertion-red, Python/Promtool/gate proof. Error absence is not delivery proof; live Grafana equality pending.