---
id: 07-eslint-rule-no-undeclared-analytics-event
epic: product-analytics-channel
title: Add no-undeclared-analytics-event ESLint rule to @repo/core-eslint
type: technical-story
status: done
feature: core-eslint
depends-on: [05-assert-feature-conformance-analyzed]
blocks: [09-documentation]
created: 2026-05-18T12:06:00Z
updated: 2026-05-18T15:44:55.963Z
---

## Goal

Add the `conformance/no-undeclared-analytics-event` rule to `@repo/core-eslint` at warn severity. The rule finds `analytics.track("X", ...)` string-literal calls in `*.use-case.ts` files and warns when `"X"` is not declared in the file's feature manifest under `analyticsEvents`. Mirrors `no-undeclared-audit` and `no-undeclared-event-publish`.

## Why

Boot-time conformance (Story 05) catches missing brands at process start, but it can't catch event-slug typos or new undeclared slugs introduced during development before the app is ever booted. The ESLint rule provides sub-second feedback in the editor and in CI, closing the latency gap.

## Done when

- `packages/core-eslint/rules/no-undeclared-analytics-event.js` exists and passes RuleTester fixtures.
- Fixtures cover: declared slug → no warning, undeclared slug → warn, non-use-case file → no-op, manifest with no use cases → no-op.
- `_manifest-ast.js` parses `analyticsEvents` arrays (extends existing AST helper).
- Rule registered in `plugin.js` and `base.js` at `"warn"` severity.
- `pnpm lint` runs the rule; all gates pass.

## In scope

- `packages/core-eslint/rules/no-undeclared-analytics-event.js` + RuleTester test file.
- `packages/core-eslint/rules/_manifest-ast.js` — `analyticsEvents` parsing addition.
- `packages/core-eslint/plugin.js` + `packages/core-eslint/base.js` — rule registration at warn.

## Out of scope

- Migrating existing use cases (no template feature declares analytics events per PRD).
- Auto-fix — warn only, no `--fix` path in this slice.

## Tasks

- [x] Add `no-undeclared-analytics-event.js` rule to `@repo/core-eslint` — rule implementation cross-checking `analytics.track("X", ...)` literal slug against manifest `analyticsEvents`, extend `_manifest-ast.js` to parse the field, RuleTester fixtures (declared passes, undeclared warns, non-use-case no-op, no-manifest no-op), register in `plugin.js` + `base.js` at `"warn"` — all gates pass on this commit.
