feat(telemetry): capture installs from published packages#328
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
blove
added a commit
that referenced
this pull request
May 16, 2026
#351) * docs(gtm): spec for analytics-foundation-1c (cockpit instrumentation) Spec 1C of the GTM motion. Three-surface cockpit instrumentation: - Outer (React shell): cockpit:recipe_opened, mode_switched, code_copied via posthog-js direct - Inner (Angular iframes, per-example): cockpit:chat_first_message, transport_connected, thread_persisted, interrupt_handled, generative_component_rendered via new @ngaf/cockpit-telemetry private library that subscribes to lifecycle signals on @ngaf/chat, @ngaf/langgraph, @ngaf/render - Cross-frame correlation via session UUID in URL params; memory-only persistence on both frames Key decisions: - Architecture B (lifecycle signals + external adapter) — libraries expose @ngaf/* tokens, adapter is private. Customer apps never emit cockpit:* events. - cockpit-telemetry uses posthog-js directly, not @ngaf/telemetry/browser (cockpit is internal product, different posture from customer libs) - main.cockpit.ts build-time entry override per example, so example reference code (main.ts, app.config.ts, components) stays pristine - Telemetry on by default in production, off on localhost unless NEXT_PUBLIC_COCKPIT_CAPTURE_LOCAL=true; honors DO_NOT_TRACK - Activation funnel = 5 signals (dropped cockpit:install_command_copied; ngaf:postinstall from PR #328 is uncorrelatable to cockpit sessions by design) - Renamed cockpit:six_signals_complete → cockpit:activation_complete - All 32 examples rolled out in batched per-category commits within this plan; canonical example: cockpit/langgraph/streaming/angular - Website docs for the three public *_LIFECYCLE tokens land as Phase 5 Phases: 0. Library lifecycle additions (~21 tests) 1. @ngaf/cockpit-telemetry private library (~24 tests, incl. permanent browser silence test) 2. React shell instrumentation (~17 tests) 3. Canonical streaming example + Chrome MCP smoke 4. 31 remaining examples in 4 category batches 5. Website docs at /docs/<lib>/lifecycle 6. Taxonomy + PostHog dashboard cleanup (drop install_command_copied, rename event + insight + dashboard, posthog:sync) Total ~65 tests, 15 new spec files. Pre-PR-#328 design adjusted to match the new ingest proxy + per-package install telemetry pattern. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(gtm): implementation plan for analytics-foundation-1c (cockpit instrumentation) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(chat): add CHAT_LIFECYCLE InjectionToken + interface Public API addition for cockpit-telemetry (and other consumers) to subscribe to per-instance chat lifecycle signals. componentReady, firstMessageSent (sticky), messageCount and inputSubmittedAt (reset on clearThread). Token only; wiring lands in next task. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(chat): wire CHAT_LIFECYCLE in ChatComponent Populates the four lifecycle signals from existing component code paths: componentReady on the first agent-resolved effect, firstMessageSent/messageCount/inputSubmittedAt in a new public submitMessage() (also driven by the chat-input submitted output), and reset (except sticky firstMessageSent) in a new public clearThread(). The token is provided component-scoped via a factory that hands ChatComponent a writable internal handle while consumers see only the readonly Signal<T> surface. Adds 6 tests covering all transitions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(chat): add onUserSubmitted coverage + clarify clearThread doc Addresses code-quality review feedback on Task 0.2. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(langgraph): add AGENT_LIFECYCLE InjectionToken + interface 8 lifecycle signals exposing transition timestamps. Wiring lands in agent.fn.ts in the next task. Three signals (interruptResolvedAt, threadCreatedAt, threadPersistedAt) require new hook points; five are derived from existing BehaviorSubjects. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(langgraph): wire AGENT_LIFECYCLE in agent.fn.ts Eight signal updates hooked into existing stream subscriptions and the agent's submit/switchThread/load-history paths. Three new hooks (interruptResolvedAt, threadCreatedAt, threadPersistedAt) — five signals derive from existing stream state. All reset on switchThread. Lifecycle surface exposed via a new `lifecycle: AgentLifecycle` field on the returned LangGraphAgent (the factory has no DI scope of its own, so this is the minimal-pollution path; consumers can re-provide the AGENT_LIFECYCLE token via standard Angular providers if needed). Mock agent updated to satisfy the new field. 10 tests cover all transitions; 154/154 langgraph suite passes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(render): add RENDER_LIFECYCLE token + service + wiring Service subscribes to the existing render-event stream and reduces to five signals. firstMountAt is sticky; the rest update on each event. Provided via provideRender() so all consumers automatically have access. All RenderEvents flow through a single emitTapped() in RenderSpecComponent, which fans out to the events output AND notifies the lifecycle service (when present). Service is injected optionally so the components remain usable without provideRender(). 5 tests cover all signal transitions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): scaffold private Nx library @ngaf/cockpit-telemetry — private (not in publishable group), Angular library, consumed by the 32 Angular examples via main.cockpit.ts build-time entry override. Mirrors @ngaf/cockpit-shell scaffold pattern. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): config token + typed event names Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): readCockpitConfigFromIframe — URL param reader Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): ActivationAggregator — 5-signal rollup with 30-min window 6 tests cover the rollup math: pre-complete state, fire-once-when-complete, idempotent signals, 30-min window reset, duration_ms property on emit. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): CockpitTelemetryService — lifecycle subscribers + posthog init Initializes posthog-js with memory persistence + parent-provided distinct_id, subscribes to CHAT/AGENT/RENDER lifecycle tokens (each optional — graceful no-op if absent), fires cockpit:* events and marks signals on the ActivationAggregator. 6 tests cover init idempotency, capture format, missing-lifecycle gracefulness, capability property stamping. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): provideCockpitTelemetry() EnvironmentProviders factory Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-telemetry): bootstrapWithCockpitHarness — main.cockpit.ts entry helper Each cockpit example's main.cockpit.ts calls this with its AppComponent + appConfig. When URL params present, telemetry providers are added; otherwise bootstraps pristine. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(cockpit-telemetry): permanent browser silence contract test When the cockpit harness is not present (no URL params), no eager import of posthog-js. Mirrors @ngaf/telemetry/browser silence pattern. Stays green permanently. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(cockpit-telemetry): declare peer deps + use lib- selector in spec - Add @angular/platform-browser, @ngaf/chat, @ngaf/langgraph, @ngaf/render to peerDependencies (consumed by harness + service). - TestComponent in harness.spec.ts uses lib- prefix per project eslint rules. - Lockfile updated to record posthog-js install for the new private lib. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): analytics module — distinct-id, properties, events, client Mirrors apps/website/src/lib/analytics/ structure. Memory-only session UUID, shouldCaptureAnalytics guard with localhost gate + DO_NOT_TRACK honoring, typed track() helper. ~10 tests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): posthog-js initialization via instrumentation-client.ts Memory persistence + parent-side session UUID. Off on localhost by default (NEXT_PUBLIC_COCKPIT_CAPTURE_LOCAL=true to override). Honors DO_NOT_TRACK. Three new env vars documented in .env.example. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): fire cockpit:recipe_opened on sidebar capability click Properties: capability, category, from_capability. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): fire cockpit:mode_switched on mode tab change Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): fire cockpit:code_copied on Code mode copy Properties: capability, surface=code_mode, file_path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): fire cockpit:code_copied on narrative docs copy buttons Two surfaces: docs_code_snippet (inline code blocks) and agentic_prompt (prompt callouts). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit): RunMode appends cockpit_did/cockpit_cap to iframe src The iframe URL now carries the session UUID + capability slug + posthog key + host so the Angular harness can correlate to the parent session. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-streaming): main.cockpit.ts harness entry Three-line harness uses bootstrapWithCockpitHarness from @ngaf/cockpit-telemetry. Pristine main.ts unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-streaming): add cockpit build configuration cockpit/<...>/project.json gains a cockpit build that uses main.cockpit.ts as the entry. apps/cockpit:serve-streaming now invokes serve:cockpit on the example. Production build unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-langgraph): wire 7 examples to cockpit-telemetry harness Add main.cockpit.ts + cockpit build/serve configurations to the remaining LangGraph cockpit examples (memory, durable-execution, subgraphs, deployment-runtime, interrupts, persistence, time-travel). Update apps/cockpit serve-* targets to use the :serve:cockpit config so the iframe loads the harness-enabled build. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-deep-agents): wire 6 examples to cockpit-telemetry harness Add main.cockpit.ts + cockpit build/serve configurations to all Deep Agents cockpit examples (sandboxes, subagents, memory, planning, filesystem, skills). Update apps/cockpit serve-* targets to use the :serve:cockpit config so the iframe loads the harness-enabled build. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-chat): wire 11 examples to cockpit-telemetry harness Add main.cockpit.ts + cockpit build/serve configurations to all chat cockpit examples (tool-calls, messages, subagents, input, a2ui, theming, threads, interrupts, timeline, generative-ui, debug). The timeline harness preserves the installEmbeddedTheme() call before bootstrap. Chat examples are launched via the serve-example.ts script; that script is updated in the render batch. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(cockpit-render): wire 6 examples to cockpit-telemetry harness Add main.cockpit.ts + cockpit build/serve configurations to all render cockpit examples (computed-functions, element-rendering, repeat-loops, state-management, spec-rendering, registry). Also update the shared serve-example.ts script so both --capability and --all modes launch the harness-enabled :serve:cockpit configuration; this covers the chat + render capabilities that don't have per-capability serve-* targets in apps/cockpit/project.json. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(website): chat/lifecycle.md — CHAT_LIFECYCLE signal docs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(website): langgraph/lifecycle.md — AGENT_LIFECYCLE signal docs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(website): render/lifecycle.md — RENDER_LIFECYCLE signal docs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(website): link lifecycle pages from each lib's landing Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(gtm): drop install_command_copied + rename activation event Activation funnel is 5 signals per Spec 1C. ngaf:postinstall is its own top-of-funnel metric, uncorrelated to cockpit sessions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(posthog): rename six-signal-activation-funnel → activation-funnel 5 steps (dropped install_command_copied), 30-minute window. posthog_id nulled to force create on next sync (PostHog will assign a new id). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(posthog): developer-funnel references activation-funnel insight Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(cockpit): polyfill CSS.escape in jsdom test setup jsdom doesn't implement CSS.escape; code-mode copy handler calls it. Tests passed but vitest flagged an unhandled error. Polyfill restores green nx test target. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(gtm): align taxonomy with implemented cockpit shell events - Rename cockpit:recipe_start → cockpit:recipe_opened (sidebar click) - Add cockpit:mode_switched (Run/Code/Docs tab change) - Add cockpit:code_copied (code mode, doc snippet, agentic prompt) - Update cockpit-recipe-completion insight to use renamed event - Document that shell events are funnel context, not activation steps Addresses code-review finding on Spec 1C. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(langgraph,cockpit-telemetry): wire AGENT_LIFECYCLE via registry Bug: CockpitTelemetryService.subscribeAgent() injected AGENT_LIFECYCLE which is never provided in DI (agent() exposes lifecycle on its return object). Three activation signals (transport_connected, thread_persisted, interrupt_handled) never fired; activation funnel was unreachable. Fix: Add AgentLifecycleRegistry to @ngaf/langgraph as an optional service. agent() registers itself if the registry is provided. provideCockpitTelemetry now provides the registry, and the service subscribes to lifecycles reactively via a signal effect. Addresses code-review item on Spec 1C. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(render): drop providedIn:root on RenderLifecycleService Service is already provided by provideRender(). The redundant providedIn:'root' caused both paths to resolve to the same singleton — removing it makes the scope follow the consumer's provideRender() call (sub-tree-friendly). Addresses code-review minor item on Spec 1C. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(website): regenerate api-docs.json for lifecycle additions Picks up CHAT_LIFECYCLE, AGENT_LIFECYCLE, RENDER_LIFECYCLE tokens + AgentLifecycleRegistry from Spec 1C. CI drift check would fail without this regeneration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
posthog-nodein@ngaf/telemetry.@ngaf/*package by patching publishabledistmanifests during release builds./api/ingestproxy and update public messaging/release docs to match the new trust contract.Verification
PATH="/Users/blove/.nvm/versions/node/v22.14.0/bin:$PATH" NX_DAEMON=false npx nx test telemetry --skip-nx-cachePATH="/Users/blove/.nvm/versions/node/v22.14.0/bin:$PATH" NX_DAEMON=false npx nx build website --skip-nx-cachePATH="/Users/blove/.nvm/versions/node/v22.14.0/bin:$PATH" NX_DAEMON=false npx nx run-many -t build --projects=chat,langgraph,ag-ui,render,a2ui,licensing,telemetry --skip-nx-cachenode libs/telemetry/scripts/apply-install-telemetry.mjs dist/libs/chat dist/libs/langgraph dist/libs/ag-ui dist/libs/render dist/libs/a2ui dist/libs/licensingdist, installed into a fresh temp project with a local ingest server, and captured 7ngaf:postinstallevents withpackage_manager=npm/package_manager_version=10.9.2.PATH="/Users/blove/.nvm/versions/node/v22.14.0/bin:$PATH" NX_DAEMON=false npx nx release version patch --dry-rungit diff --checkrg '@ngaf/partial-json|libs/partial-json' --glob '!docs/superpowers/**' --glob '!node_modules/**' --glob '!dist/**'