agentleFS
dream-horizon-orgdream-horizon-org/pulse/pulse-web-otel/CLAUDE.md

pulse / pulse-web-otel

CLAUDE.md44 starsChanged 5 months agoApache-2.0View on GitHub

Per-package operating manual. Auto-loaded by Claude Code (hierarchical CLAUDE.md) alongside the repo-root constitution. See .agents/rules/pulse-web-otel-contract.mdc and .agents/rules/pulse-web-otel-conventions.mdc (symlinked as .cursor/rules/web-sdk.mdc and .cursor/rules/pulse-web-otel.mdc) for contract vs conventions. Highlights worth restating because they change agent behaviour:

The file

We split this CLAUDE.md into the rules it gives an agent

7 rules. About 0 are common, 0 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Test: vitest — yarn test:run (CI) or yarn test (watch)

    line 9
  2. Very specific:

    After substantive SDK edits: yarn e2e:web-sdk-gates from this package (Playwright gate bundle: M1–M4, web vitals, clicks, network, screen …

    line 40
  3. Very specific:

    Use fake-indexeddb for IDB persistence tests.

    line 43
  4. Very specific:

    Don't add lodash, moment, or any heavy dep.

    line 69
  5. Very specific:

    Don't import from @opentelemetry/sdk-node — Node-only, breaks in browser builds.

    line 70
  6. Very specific:

    Don't write to console.* outside src/pulse-web-logger.ts — every log routes through the logger so consumers can silence us.

    line 71
  7. Very specific:

    Don't change src/index.ts exports without bumping the version.

    line 72

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

pulse-web-otel — Package context

Per-package operating manual. Auto-loaded by Claude Code (hierarchical CLAUDE.md) alongside the repo-root constitution.

Fast facts

  • Package: @dreamhorizonorg/pulse-web (package.json name), 0.0.3 (pre-release)
  • Build: tsup → dist/
  • Test: vitest — yarn test:run (CI) or yarn test (watch)
  • Typecheck: yarn lint (= tsc --noEmit, not eslint)
  • Bundle gate: yarn size-limit
  • Demo: examples/ecommerce-demo/ (Vite app on :3002)

Layer rules

See .agents/rules/pulse-web-otel-contract.mdc and .agents/rules/pulse-web-otel-conventions.mdc (symlinked as .cursor/rules/web-sdk.mdc and .cursor/rules/pulse-web-otel.mdc) for contract vs conventions. Highlights worth restating because they change agent behaviour:

  • platform = 'web' on every signal. Not optional.
  • pulse.type enum: see src/semconv.ts / docs/sdk-core/data-contract/SPEC.md. Don't invent new values without an ADR.
  • src/instrumentations/<name>.ts is the registration surface; never touch io.opentelemetry.* namespacing — that's upstream.
  • Public API: what src/index.ts exports (Pulse, config types, CLSThresholds, FCPThresholds, INPThresholds, LCPThresholds, TTFBThresholds, …). Consumers don't pin internal paths.

Where things live

ConcernPath
OTLP exporter wiringsrc/exporters.ts
Sampling rulessrc/sampling/
Instrumentation registrysrc/instrumentation-registry.ts
Interaction (sequences)src/instrumentations/interaction.ts + src/interactions/
Session lifecyclesrc/instrumentations/session.ts
Remote configsrc/remote-config.ts
Consent gatesrc/consent.ts
Persistence (IDB/LS)src/persistence/
Testssrc/__tests__/ (co-located in some sub-dirs too)

Test patterns

  • After substantive SDK edits: yarn e2e:web-sdk-gates from this package (Playwright gate bundle: M1–M4, web vitals, clicks, network, screen navigation; Chromium). Requires demo deps installed.
  • Vitest with --run for one-shot. Use file paths to scope: yarn test:run src/instrumentations/interaction.test.ts.
  • Mock at the OTLP exporter boundary — never mock OTel SDK internals; they're upstream and the test will silently rot.
  • Use fake-indexeddb for IDB persistence tests; never hit real IDB.
  • Network client spans: assert pulse.type (network.<status> pattern), http.request.method, http.response.status_code — see docs/instrumentations/network/SPEC.md.

Sharp edges (start short — agent appends here)

  • Don't read localStorage synchronously at module init. Some host apps load us in a Web Worker context where window.localStorage is undefined. Use the persistence module which guards.
  • Screen navigation: screen_load + screen_session OTLP spans from src/instrumentations/navigation.ts when enabled. Web does not emit a separate screen_interactive span — tti lives on screen_load. See docs/instrumentations/screen-signals/SPEC.md. Router hooks call Pulse.setScreenName for screen.name on other telemetry.
  • Click heatmap is deferred. See docs/instrumentations/interactions/SPEC.md §7 / §9.
  • Session-storage size limits. localStorage quota = ~5MB on most browsers. The persistence module truncates oldest spans first; don't add unbounded queues.

Recurring agent failures (start empty — agent appends here)

<!-- When Ralph fails the same way twice, append a one-liner here so future iters skip it. -->

Do X here

TaskWhere to do it
Add a new instrumentationsrc/instrumentations/<name>.ts + register in src/instrumentation-registry.ts + test in src/__tests__/
Add a new pulse.type valueUpdate src/constants/ / semconv + ADR in docs/ or repo planning
Add an exporter integrationsrc/integrations/ (per-framework adapter)
Tweak samplingsrc/sampling/ — keep deterministic across page loads
Add a feature gatesrc/feature-gate.ts

Do NOT do here

  • Don't add lodash, moment, or any heavy dep. Bundle size is gated by size-limit.
  • Don't import from @opentelemetry/sdk-node — Node-only, breaks in browser builds.
  • Don't write to console.* outside src/pulse-web-logger.ts — every log routes through the logger so consumers can silence us.
  • Don't change src/index.ts exports without bumping the version. It's a public API surface.

Reference docs

  • prd/README.md — where PRDs live; symlink PRD.md → prd/<slug>.md for Ralph (or PRD_PATH)
  • docs/instrumentations/integration/SPEC.md — host-app integration entry (exports, init, framework pointers). Agent skill: integrate-pulse-web-sdk (.agents/skills/).
  • docs/sdk-core/SPEC.md — sdk-core index (links to split topics)
  • docs/sdk-core/data-contract/SPEC.md — pulse.type + shared attributes
  • docs/instrumentations/ — per-feature holy-grail SPECs (errors, network, …)
  • .agents/rules/ contract + conventions (same rules via .cursor/rules/ symlinks)

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.