From 0de706e437230ba73c8c24801a88e228966aaa47 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Fri, 4 Sep 2026 21:19:02 -0700 Subject: [PATCH 1/6] feat(telemetry): collect installs and development progress for founder outreach --- .github/workflows/publish.yml | 6 + .gitignore | 3 + apps/website/content/AGENTS.md.template | 23 + apps/website/content/CLAUDE.md.template | 23 + .../content/docs/ag-ui/api/api-docs.json | 4 +- .../content/docs/langgraph/api/api-docs.json | 4 +- .../content/docs/render/api/api-docs.json | 12 + apps/website/public/AGENTS.md | 23 + apps/website/public/CLAUDE.md | 23 + apps/website/src/app/layout.tsx | 3 + apps/website/src/app/privacy/page.spec.tsx | 18 +- apps/website/src/app/privacy/page.tsx | 65 +- .../src/components/docs/CopyButton.tsx | 2 + .../src/components/docs/mdx/CodeBlock.tsx | 2 + .../components/landing/InstallDialog.spec.tsx | 13 + .../src/components/landing/InstallDialog.tsx | 5 +- .../components/shared/WebsiteSignals.spec.tsx | 17 + .../src/components/shared/WebsiteSignals.tsx | 12 + .../src/lib/growth/acquisition-session.ts | 53 ++ .../src/lib/growth/form-client.spec.ts | 33 + apps/website/src/lib/growth/form-client.ts | 43 +- .../src/lib/growth/website-collector.spec.ts | 135 ++++ .../src/lib/growth/website-collector.ts | 220 ++++++ eslint.config.mjs | 1 + libs/ag-ui/README.md | 63 ++ libs/ag-ui/ng-package.json | 19 +- libs/ag-ui/package.json | 20 +- libs/ag-ui/project.json | 33 +- libs/ag-ui/src/lib/package-version.ts | 3 + libs/ag-ui/src/lib/provide-agent.ts | 6 +- libs/ag-ui/src/lib/to-agent.spec.ts | 110 +++ libs/ag-ui/src/lib/to-agent.ts | 59 +- libs/ag-ui/src/test-setup.ts | 2 + libs/chat/README.md | 63 ++ libs/chat/ng-package.json | 48 +- libs/chat/package.json | 18 +- libs/chat/project.json | 33 +- .../compositions/chat/chat.component.spec.ts | 19 + .../lib/compositions/chat/chat.component.ts | 9 + libs/chat/src/lib/package-version.ts | 3 + libs/chat/src/test-setup.ts | 3 + .../observability/install-collector.spec.ts | 46 ++ libs/langgraph/README.md | 63 ++ libs/langgraph/ng-package.json | 19 +- libs/langgraph/package.json | 20 +- libs/langgraph/project.json | 33 +- libs/langgraph/src/lib/agent.fn.spec.ts | 8 + libs/langgraph/src/lib/agent.fn.ts | 5 +- libs/langgraph/src/lib/agent.provider.ts | 6 +- libs/langgraph/src/lib/agent.types.ts | 6 +- .../internals/stream-manager.bridge.spec.ts | 144 ++++ .../lib/internals/stream-manager.bridge.ts | 81 ++- libs/langgraph/src/lib/package-version.ts | 3 + libs/langgraph/src/test-setup.ts | 2 + libs/render/README.md | 63 ++ libs/render/ng-package.json | 19 +- libs/render/package.json | 18 +- libs/render/project.json | 31 +- libs/render/src/lib/development-mount.spec.ts | 107 +++ libs/render/src/lib/package-version.ts | 3 + .../src/lib/render-element.component.ts | 28 + libs/render/src/lib/render-spec.component.ts | 12 + libs/render/src/lib/render.types.ts | 2 + libs/render/src/test-setup.ts | 3 + libs/telemetry/README.md | 98 ++- libs/telemetry/install/assemble-package.mjs | 47 ++ libs/telemetry/install/bridge.cjs | 34 + libs/telemetry/install/collector.cjs | 125 ++++ libs/telemetry/install/collector.spec.mjs | 301 +++++++++ libs/telemetry/install/discovery.spec.mjs | 225 +++++++ libs/telemetry/install/files.cjs | 27 + libs/telemetry/install/git-context.cjs | 215 ++++++ libs/telemetry/install/identity.cjs | 37 ++ libs/telemetry/install/packaging.spec.mjs | 61 ++ libs/telemetry/install/policy.cjs | 54 ++ libs/telemetry/install/postinstall.cjs | 20 + libs/telemetry/install/verify-pack.mjs | 288 ++++++++ libs/telemetry/project.json | 14 + .../scripts/verify-angular-install-bridge.mjs | 315 +++++++++ .../scripts/verify-development-bundle.mjs | 157 +++++ .../src/browser/development/announcements.ts | 136 ++++ .../src/browser/development/collector.ts | 316 +++++++++ .../src/browser/development/runtime.spec.ts | 628 ++++++++++++++++++ .../src/browser/development/runtime.ts | 131 ++++ .../src/browser/development/session.ts | 190 ++++++ .../src/browser/development/types.ts | 52 ++ libs/telemetry/src/browser/public-api.ts | 13 + libs/telemetry/vite.config.mts | 6 +- 88 files changed, 5358 insertions(+), 108 deletions(-) create mode 100644 apps/website/src/components/shared/WebsiteSignals.spec.tsx create mode 100644 apps/website/src/components/shared/WebsiteSignals.tsx create mode 100644 apps/website/src/lib/growth/acquisition-session.ts create mode 100644 apps/website/src/lib/growth/website-collector.spec.ts create mode 100644 apps/website/src/lib/growth/website-collector.ts create mode 100644 libs/ag-ui/src/lib/package-version.ts create mode 100644 libs/chat/src/lib/package-version.ts create mode 100644 libs/growth/src/lib/observability/install-collector.spec.ts create mode 100644 libs/langgraph/src/lib/package-version.ts create mode 100644 libs/render/src/lib/development-mount.spec.ts create mode 100644 libs/render/src/lib/package-version.ts create mode 100644 libs/telemetry/install/assemble-package.mjs create mode 100644 libs/telemetry/install/bridge.cjs create mode 100644 libs/telemetry/install/collector.cjs create mode 100644 libs/telemetry/install/collector.spec.mjs create mode 100644 libs/telemetry/install/discovery.spec.mjs create mode 100644 libs/telemetry/install/files.cjs create mode 100644 libs/telemetry/install/git-context.cjs create mode 100644 libs/telemetry/install/identity.cjs create mode 100644 libs/telemetry/install/packaging.spec.mjs create mode 100644 libs/telemetry/install/policy.cjs create mode 100644 libs/telemetry/install/postinstall.cjs create mode 100644 libs/telemetry/install/verify-pack.mjs create mode 100644 libs/telemetry/scripts/verify-angular-install-bridge.mjs create mode 100644 libs/telemetry/scripts/verify-development-bundle.mjs create mode 100644 libs/telemetry/src/browser/development/announcements.ts create mode 100644 libs/telemetry/src/browser/development/collector.ts create mode 100644 libs/telemetry/src/browser/development/runtime.spec.ts create mode 100644 libs/telemetry/src/browser/development/runtime.ts create mode 100644 libs/telemetry/src/browser/development/session.ts create mode 100644 libs/telemetry/src/browser/development/types.ts diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 909a6f74e..d3d45a01b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -59,6 +59,12 @@ jobs: env: RELEASE_TAG: ${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || '' }} + - name: Verify installed collectors and development-only bundles + run: | + npx nx build growth --skip-nx-cache + npx nx run telemetry:test-install-pack --skip-nx-cache + npx nx run telemetry:test-development-bundle --skip-nx-cache + # Trusted publishing is configured per-package on npm; no NPM_TOKEN needed. # The OIDC token from id-token: write authenticates this workflow as a # trusted publisher for each @threadplane/* package. Provenance attestations are diff --git a/.gitignore b/.gitignore index 7981f2dee..577816eed 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,9 @@ keys/ # Aborted fixture-record runs strand raw recordings under a committed path **/e2e/fixtures/.staging/ +# Shared install collector staged before each library is packaged. +libs/*/.install-collector/ + # Growth research generated deployment artifacts apps/growth-research/.dawn/ apps/growth-research/.deployment/ diff --git a/apps/website/content/AGENTS.md.template b/apps/website/content/AGENTS.md.template index d6912c8e6..d32364a30 100644 --- a/apps/website/content/AGENTS.md.template +++ b/apps/website/content/AGENTS.md.template @@ -12,6 +12,29 @@ Supported Angular majors: 20, 21, and 22. ## Install npm install @threadplane/chat @threadplane/langgraph @langchain/core @langchain/langgraph-sdk marked +The chat, LangGraph, AG-UI, and render packages include automatic install collection +for local and CI execution: package/environment details, a random installation ID, +configured Git name/full email, and repository provider/owner hints when available. +Set `DO_NOT_TRACK=1` or `TPLANE_TELEMETRY_DISABLED=1` before installation to disable +it. Package-manager script controls are respected. A usable install email can qualify +for a short founder welcome sequence after linked development-browser use, capped +at three emails with unsubscribe and reply stops. CI alone does not trigger it. +The package-local correlation token contains no email; copied/cached packages can +retain it, so it does not verify a person. No registration is required. +See https://threadplane.ai/privacy. + + +Supported runtime/browser collection is automatic only in Angular development mode. +Production builds, SSR, imports, and unused construction are inert. It sends closed +progress milestones with package/version and random browser-origin/session IDs, never +conversation content or private URLs. Adapter `telemetry: false` disables it; a custom +sink replaces the automatic destination, including nested chat JSON rendering. Use +`setDevelopmentCollectionEnabled(false)` from `@threadplane/telemetry/browser`, or set +browser localStorage `THREADPLANE_TELEMETRY_DISABLED=1` and reload. Development console +announcements need no click to acknowledge progress. Linked non-CI install and runtime +evidence can qualify the install email for the founder sequence described above. +Standalone render also accepts `provideRender({ telemetry: false })`. + ## Key requirement `injectAgent()` MUST be called within an Angular injection context (component constructor or field initializer). Calling it in ngOnInit or any async context throws "NG0203: inject() must be called from an injection context". diff --git a/apps/website/content/CLAUDE.md.template b/apps/website/content/CLAUDE.md.template index d6912c8e6..d32364a30 100644 --- a/apps/website/content/CLAUDE.md.template +++ b/apps/website/content/CLAUDE.md.template @@ -12,6 +12,29 @@ Supported Angular majors: 20, 21, and 22. ## Install npm install @threadplane/chat @threadplane/langgraph @langchain/core @langchain/langgraph-sdk marked +The chat, LangGraph, AG-UI, and render packages include automatic install collection +for local and CI execution: package/environment details, a random installation ID, +configured Git name/full email, and repository provider/owner hints when available. +Set `DO_NOT_TRACK=1` or `TPLANE_TELEMETRY_DISABLED=1` before installation to disable +it. Package-manager script controls are respected. A usable install email can qualify +for a short founder welcome sequence after linked development-browser use, capped +at three emails with unsubscribe and reply stops. CI alone does not trigger it. +The package-local correlation token contains no email; copied/cached packages can +retain it, so it does not verify a person. No registration is required. +See https://threadplane.ai/privacy. + + +Supported runtime/browser collection is automatic only in Angular development mode. +Production builds, SSR, imports, and unused construction are inert. It sends closed +progress milestones with package/version and random browser-origin/session IDs, never +conversation content or private URLs. Adapter `telemetry: false` disables it; a custom +sink replaces the automatic destination, including nested chat JSON rendering. Use +`setDevelopmentCollectionEnabled(false)` from `@threadplane/telemetry/browser`, or set +browser localStorage `THREADPLANE_TELEMETRY_DISABLED=1` and reload. Development console +announcements need no click to acknowledge progress. Linked non-CI install and runtime +evidence can qualify the install email for the founder sequence described above. +Standalone render also accepts `provideRender({ telemetry: false })`. + ## Key requirement `injectAgent()` MUST be called within an Angular injection context (component constructor or field initializer). Calling it in ngOnInit or any async context throws "NG0203: inject() must be called from an injection context". diff --git a/apps/website/content/docs/ag-ui/api/api-docs.json b/apps/website/content/docs/ag-ui/api/api-docs.json index e34c99ddf..79757f7df 100644 --- a/apps/website/content/docs/ag-ui/api/api-docs.json +++ b/apps/website/content/docs/ag-ui/api/api-docs.json @@ -390,7 +390,7 @@ { "name": "telemetry", "type": "false | AgentRuntimeTelemetrySink", - "description": "Optional app-owned sink. Supply one to receive runtime lifecycle events.", + "description": "Omit to enable automatic development-only collection. Set `false` to disable.\nAn app-owned sink replaces the automatic destination and receives the\nexisting runtime lifecycle callbacks.", "optional": true }, { @@ -540,7 +540,7 @@ { "name": "telemetry", "type": "false | AgentRuntimeTelemetrySink", - "description": "Optional app-owned sink. Supply one to receive runtime lifecycle events.", + "description": "Omit to enable automatic development-only collection. Set `false` to disable.\nAn app-owned sink replaces the automatic destination and receives the\nexisting runtime lifecycle callbacks.", "optional": true } ], diff --git a/apps/website/content/docs/langgraph/api/api-docs.json b/apps/website/content/docs/langgraph/api/api-docs.json index 060243860..8b09bb050 100644 --- a/apps/website/content/docs/langgraph/api/api-docs.json +++ b/apps/website/content/docs/langgraph/api/api-docs.json @@ -919,7 +919,7 @@ { "name": "telemetry", "type": "false | AgentRuntimeTelemetrySink", - "description": "Optional app-owned sink. Supply one to receive runtime lifecycle events.", + "description": "Omit to enable automatic development-only collection. Set `false` to disable.\nAn app-owned sink replaces the automatic destination and receives the\nexisting runtime lifecycle callbacks.", "optional": true }, { @@ -1061,7 +1061,7 @@ { "name": "telemetry", "type": "false | AgentRuntimeTelemetrySink", - "description": "Optional app-owned sink. Supply one to receive runtime lifecycle events.", + "description": "Omit to enable automatic development-only collection. Set `false` to disable.\nAn app-owned sink replaces the automatic destination and receives the\nexisting runtime lifecycle callbacks.", "optional": true }, { diff --git a/apps/website/content/docs/render/api/api-docs.json b/apps/website/content/docs/render/api/api-docs.json index b7dfe6057..ae142b4a6 100644 --- a/apps/website/content/docs/render/api/api-docs.json +++ b/apps/website/content/docs/render/api/api-docs.json @@ -171,6 +171,12 @@ "type": "InputSignal", "description": "", "optional": false + }, + { + "name": "telemetry", + "type": "InputSignal", + "description": "Disable automatic development collection for this render tree.", + "optional": false } ], "methods": [ @@ -276,6 +282,12 @@ "type": "StateStore", "description": "Backing state store that `$bindState` paths read from and interactive elements write to.", "optional": true + }, + { + "name": "telemetry", + "type": "boolean", + "description": "Set false to disable automatic development browser collection for this render tree.", + "optional": true } ], "examples": [] diff --git a/apps/website/public/AGENTS.md b/apps/website/public/AGENTS.md index f35ac8aaa..c5af7ad06 100644 --- a/apps/website/public/AGENTS.md +++ b/apps/website/public/AGENTS.md @@ -12,6 +12,29 @@ Supported Angular majors: 20, 21, and 22. ## Install npm install @threadplane/chat @threadplane/langgraph @langchain/core @langchain/langgraph-sdk marked +The chat, LangGraph, AG-UI, and render packages include automatic install collection +for local and CI execution: package/environment details, a random installation ID, +configured Git name/full email, and repository provider/owner hints when available. +Set `DO_NOT_TRACK=1` or `TPLANE_TELEMETRY_DISABLED=1` before installation to disable +it. Package-manager script controls are respected. A usable install email can qualify +for a short founder welcome sequence after linked development-browser use, capped +at three emails with unsubscribe and reply stops. CI alone does not trigger it. +The package-local correlation token contains no email; copied/cached packages can +retain it, so it does not verify a person. No registration is required. +See https://threadplane.ai/privacy. + + +Supported runtime/browser collection is automatic only in Angular development mode. +Production builds, SSR, imports, and unused construction are inert. It sends closed +progress milestones with package/version and random browser-origin/session IDs, never +conversation content or private URLs. Adapter `telemetry: false` disables it; a custom +sink replaces the automatic destination, including nested chat JSON rendering. Use +`setDevelopmentCollectionEnabled(false)` from `@threadplane/telemetry/browser`, or set +browser localStorage `THREADPLANE_TELEMETRY_DISABLED=1` and reload. Development console +announcements need no click to acknowledge progress. Linked non-CI install and runtime +evidence can qualify the install email for the founder sequence described above. +Standalone render also accepts `provideRender({ telemetry: false })`. + ## Key requirement `injectAgent()` MUST be called within an Angular injection context (component constructor or field initializer). Calling it in ngOnInit or any async context throws "NG0203: inject() must be called from an injection context". diff --git a/apps/website/public/CLAUDE.md b/apps/website/public/CLAUDE.md index f35ac8aaa..c5af7ad06 100644 --- a/apps/website/public/CLAUDE.md +++ b/apps/website/public/CLAUDE.md @@ -12,6 +12,29 @@ Supported Angular majors: 20, 21, and 22. ## Install npm install @threadplane/chat @threadplane/langgraph @langchain/core @langchain/langgraph-sdk marked +The chat, LangGraph, AG-UI, and render packages include automatic install collection +for local and CI execution: package/environment details, a random installation ID, +configured Git name/full email, and repository provider/owner hints when available. +Set `DO_NOT_TRACK=1` or `TPLANE_TELEMETRY_DISABLED=1` before installation to disable +it. Package-manager script controls are respected. A usable install email can qualify +for a short founder welcome sequence after linked development-browser use, capped +at three emails with unsubscribe and reply stops. CI alone does not trigger it. +The package-local correlation token contains no email; copied/cached packages can +retain it, so it does not verify a person. No registration is required. +See https://threadplane.ai/privacy. + + +Supported runtime/browser collection is automatic only in Angular development mode. +Production builds, SSR, imports, and unused construction are inert. It sends closed +progress milestones with package/version and random browser-origin/session IDs, never +conversation content or private URLs. Adapter `telemetry: false` disables it; a custom +sink replaces the automatic destination, including nested chat JSON rendering. Use +`setDevelopmentCollectionEnabled(false)` from `@threadplane/telemetry/browser`, or set +browser localStorage `THREADPLANE_TELEMETRY_DISABLED=1` and reload. Development console +announcements need no click to acknowledge progress. Linked non-CI install and runtime +evidence can qualify the install email for the founder sequence described above. +Standalone render also accepts `provideRender({ telemetry: false })`. + ## Key requirement `injectAgent()` MUST be called within an Angular injection context (component constructor or field initializer). Calling it in ngOnInit or any async context throws "NG0203: inject() must be called from an injection context". diff --git a/apps/website/src/app/layout.tsx b/apps/website/src/app/layout.tsx index fb1422523..d2d5addc7 100644 --- a/apps/website/src/app/layout.tsx +++ b/apps/website/src/app/layout.tsx @@ -17,6 +17,8 @@ import { SITE_ORIGIN, } from '../lib/site-metadata'; import { getFormPolicy } from '../lib/growth/form-policy'; +import { WebsiteSignals } from '../components/shared/WebsiteSignals'; +import { websiteContentCatalog } from '../lib/growth/website-content'; const garamond = EB_Garamond({ subsets: ['latin'], @@ -78,6 +80,7 @@ export default function RootLayout({ reason — do not mount its component builders individually. */} +