feat(gtm): Spec 1C — cockpit instrumentation (analytics-foundation 1c)#351
Merged
Conversation
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>
…nstrumentation) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>
Addresses code-quality review feedback on Task 0.2. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>
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>
@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>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…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>
…ers + 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>
…rs factory Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…s 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>
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>
- 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>
…ient 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>
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>
Properties: capability, category, from_capability. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Properties: capability, surface=code_mode, file_path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two surfaces: docs_code_snippet (inline code blocks) and agentic_prompt (prompt callouts). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
Three-line harness uses bootstrapWithCockpitHarness from @ngaf/cockpit-telemetry. Pristine main.ts unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>
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>
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>
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>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
- 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>
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>
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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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>
4 tasks
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
Spec 1C populates the developer-funnel dashboard from Spec 1A with real cohort data by instrumenting cockpit's three surfaces (React shell + 31 Angular iframes + cross-frame correlation), while keeping example reference code pristine via build-time entry override.
Architecture: Lifecycle tokens + external adapter (Architecture B). Cockpit-telemetry subscribes to optional lifecycle tokens and `AgentLifecycleRegistry` (see below) — no telemetry code lands in example reference code.
Spec & Plan
Notable design decisions
What's NOT in this PR (deferred to operator with credentials)
I'll run the smoke + PostHog sync after merge.
Test plan
🤖 Generated with Claude Code