diff --git a/context/agents/error-tracking/capture-exceptions.md b/context/agents/error-tracking/capture-exceptions.md new file mode 100644 index 00000000..5c14e6d5 --- /dev/null +++ b/context/agents/error-tracking/capture-exceptions.md @@ -0,0 +1,42 @@ +--- +type: capture-exceptions +flow: error-tracking +label: Wire up exception capture +model_pi: openai/gpt-5.6-sol +effort_pi: medium +model_sdk: claude-sonnet-4-6 +effort_sdk: high +skills: [integration-v2-error-tracking-step, posthog-best-practices] +allowedTools: [Read, Write, Edit, Glob, Grep] +disallowedTools: [enqueue_task] +dependsOn: [install, init] +--- + +## Goal + +Make the errors the app does not catch reach PostHog, by whatever means the +SDK offers for that. Which means depends on the SDK: some autocapture +exceptions once you enable it at init, some wire into the framework's own +error handler, some give you a boundary to mount at the app entry. Follow the +docs and the reference example for this one, and set it up in one place — +never manual capture calls sprinkled across files. + +The SDK is installed and initialized — either it already was, or the install +and init tasks before you did it (see their handoffs); build on that, do not +re-check it. + +This is an instrument-only task. Do not install dependencies, run the build, +run tests, or start the app — the user-driven test-setup step at the end of +the flow verifies, when the user wants it. Do not touch the build config +either way; when the flow includes a configure task, it owns those files. +Stay inside this project's directory and set up that one place; that is the +whole job. + +## How you know you succeeded + +An error the app does not catch reaches PostHog, through the mechanism this +SDK gives you rather than one you invented. You did not install anything, run +a build, lint, or tests, search outside the project, or read through the whole +app or hand-wrap individual components or routes. Your handoff names the files +you changed and the capture mechanism, so the report can explain it to the +user. diff --git a/context/agents/error-tracking/configure.md b/context/agents/error-tracking/configure.md new file mode 100644 index 00000000..3b0e7e42 --- /dev/null +++ b/context/agents/error-tracking/configure.md @@ -0,0 +1,47 @@ +--- +type: configure +flow: error-tracking +label: Apply build-config changes +model_pi: openai/gpt-5.6-sol +effort_pi: medium +model_sdk: claude-sonnet-4-6 +effort_sdk: medium +skills: [] +allowedTools: [Read, Write, Edit, Glob, Grep, Bash, load_skill_menu, install_skill] +disallowedTools: [enqueue_task] +dependsOn: [capture-exceptions] +--- + +## Goal + +Make this project's production build emit and upload source maps (or, for Go +and Rust, native debug symbols). Install the skill your task input names +(`install_skill` with the `skillId`) and read it — it is the source of truth +for the per-framework build-config and the uploader wiring. + +Two of the skill's steps are yours: + +- **"Apply build-config changes"** — make the bundler / build-config edits the + skill instructs for this platform, so the build produces and injects the + chunk IDs PostHog needs and runs the uploader. +- **"Make credentials available at build time"** — do the skill's step so the + build can read the upload credentials from the environment. If it calls for a + loader (e.g. `dotenv`), install it SILENTLY with the project's package + manager. Skip this step entirely when the platform already auto-loads `.env`. + +Install every dependency with the project's own package manager: call +`detect_package_manager` before the first install and use its answer, +translating any `npm install` the skill or docs show (`pnpm add -D …`, +`yarn add -D …`). In a pnpm or yarn workspace, npm fails outright on +`workspace:*` dependencies (`EUNSUPPORTEDPROTOCOL`) — that error means the +wrong manager, never a flag to retry with. + +Do not write any credential values and do not create env files — the +`credentials` task owns that, in parallel with you. Do not run the build. + +## How you know you succeeded + +The build config carries the skill's source-map / debug-symbol changes and can +read its credentials from the environment at build time. Your handoff names +every file you changed and the exact build-config keys you added, so the CI +task can wire the same variables through the pipeline. diff --git a/context/agents/error-tracking/credentials.md b/context/agents/error-tracking/credentials.md new file mode 100644 index 00000000..dea87ae3 --- /dev/null +++ b/context/agents/error-tracking/credentials.md @@ -0,0 +1,57 @@ +--- +type: credentials +flow: error-tracking +label: Get and write the upload credentials +model_pi: openai/gpt-5.6-sol +effort_pi: medium +model_sdk: claude-sonnet-4-6 +effort_sdk: medium +skills: [] +allowedTools: [Read, Write, Edit, Glob, Grep, Bash, load_skill_menu, install_skill, wizard_ask] +disallowedTools: [enqueue_task] +dependsOn: [] +--- + +## Goal + +Put the PostHog source-map upload credentials into this project's environment. +Install the skill your task input names (`install_skill` with the `skillId`) +and follow its **"Write credentials to the env file"** step for the variable +names and the env file to pick. + +The upload needs a PostHog **personal API key** at build time. Only the user can +mint one — never call the PostHog API or any tool to create it. Get it and +write it in this one task (the key never survives across tasks): + +1. Ask with `wizard_ask`, exactly: + `{ id: "api-key", prompt: "Paste your PostHog personal API key below.\n\nDon't have one yet? Create one here:\n\n\nWhen creating the key, choose the 'Source map upload' preset, then come back and paste it here.", kind: "text", sensitive: true }` + You receive `{ secretRef: "secret:..." }` — a vaulted reference, never the raw + value. If `wizard_ask` is unavailable (non-interactive run), report this task + with status `not needed` and say in your handoff that the user must create + the key and set the variables themselves; do not block. +2. Pick the env file per the skill (reuse the one PostHog's SDK already writes + its `POSTHOG_*` vars to, when there is one). Call `check_env_keys` on it + first (it returns present/absent, never values — never read the file + directly). +3. Call `set_env_values`, passing the secretRef as a value object, not a + literal string — e.g. + `values: { "POSTHOG_CLI_API_KEY": { secretRef: "" }, "POSTHOG_CLI_PROJECT_ID": "", "POSTHOG_CLI_HOST": "" }`. + The exact variable names follow the skill's per-uploader convention. The + wizard resolves the ref locally, so you never see the key value. +4. Document the same variable names for other developers: append them to + `.env.example` (create it if the project has none) with empty or + placeholder values — never a real value, and never the key itself. The + example file is committed and is the only `.env*` you may write directly; + it is how the next developer, and the next wizard run's `check_env_keys`, + learns the project expects these variables. + +Replace ``, ``, and `` from your project +context. Do not touch the build config — the `configure` task owns that. + +## How you know you succeeded + +The env file holds the upload variables (the key as a resolved secret, the +non-secret project id and host as literals), written through the wizard tools, +never hardcoded in source, and `.env.example` documents the same names with +placeholders. Your handoff names the env file and every variable name — never +a value — so the CI task carries the same names into the pipeline. diff --git a/context/agents/error-tracking/init.md b/context/agents/error-tracking/init.md new file mode 100644 index 00000000..608a3bec --- /dev/null +++ b/context/agents/error-tracking/init.md @@ -0,0 +1,33 @@ +--- +type: init +flow: error-tracking +label: Set up PostHog initialization +model_pi: openai/gpt-5.6-sol +effort_pi: low +model_sdk: claude-sonnet-4-6 +effort_sdk: medium +skills: [integration-v2-init, posthog-best-practices] +allowedTools: [Read, Write, Edit, Glob, Grep] +disallowedTools: [enqueue_task] +dependsOn: [] +--- + +## Goal + +Make sure PostHog is initialized. If the project already has a working +`posthog.init(...)` (or the framework's equivalent) with its env keys wired, +leave it alone and say so in your handoff. If it doesn't, create it following +your skill — it owns the how: the framework's init point, the env-var wiring +through the wizard tools, and `.env.example`. + +You only exist in this flow because the user asked for error tracking on a +repo without PostHog. Initialize the SDK so exceptions can flow and stop — +no instrumentation, no extras. Don't set up exception capture either way; +the capture-exceptions task after you owns that. + +## How you know you succeeded + +An init point exists with the PostHog env keys present — whether it already +did or you just created it — keys in the env file, never hardcoded. Your +handoff names the files involved and how the client is constructed, so the +capture-exceptions task can find the init options without re-discovering them. diff --git a/context/agents/error-tracking/install.md b/context/agents/error-tracking/install.md new file mode 100644 index 00000000..14a2e7ff --- /dev/null +++ b/context/agents/error-tracking/install.md @@ -0,0 +1,31 @@ +--- +type: install +flow: error-tracking +label: Add the PostHog SDK to the manifest +model_pi: openai/gpt-5.6-sol +effort_pi: low +model_sdk: claude-haiku-4-5-20251001 +skills: [integration-v2-install] +allowedTools: [Read, Edit, Glob, Grep, Bash] +disallowedTools: [enqueue_task] +dependsOn: [] +--- + +## Goal + +Make sure the PostHog SDK is in the manifest. If it's already installed, +leave it alone and say so in your handoff. If it isn't, install it following +your skill — it owns the how: the package manager rules, the version rules, +what counts as an environment failure, and the fallback. + +You only exist in this flow because the user asked for error tracking on a +repo without PostHog. Install the SDK the errors will report through (the +server library too, if the app runs server-side code) and stop — no +instrumentation, no extras. + +## How you know you succeeded + +The SDK is declared in the manifest at a real version — whether it already +was or you just installed it — or your handoff plainly says why the +environment stopped you. Your handoff names the manifest and the package, so +later steps import it under the name they will actually get. diff --git a/context/agents/error-tracking/report.md b/context/agents/error-tracking/report.md new file mode 100644 index 00000000..366611a0 --- /dev/null +++ b/context/agents/error-tracking/report.md @@ -0,0 +1,65 @@ +--- +type: report +flow: error-tracking +label: Summarise and hand off +sink: true +model_pi: openai/gpt-5.6-luna +effort_pi: low +model_sdk: claude-sonnet-4-6 +effort_sdk: medium +skills: [] +allowedTools: [Read, Glob, Grep, Write, posthog_exec] +disallowedTools: [enqueue_task] +dependsOn: [capture-exceptions, wire-ci, test-setup] +--- + +## Goal + +Tell the user what error tracking now does for them and what they still have +to do, from the handoffs of every task in the run. `read_handoffs` gives you +each task's report — the capture mechanism, the files changed, the env +variable names, the CI secret to create, and any deploy path that could not be +traced. Do not re-derive any of it from the project. + +First, turn on the Error Tracking product for the team (`products-enable` +through `posthog_exec`) so the captured exceptions have a UI to land in. If +the call fails or the tool is missing, carry it as a follow-up — never fail +the report over it. + +Write the hand-off to `posthog-error-tracking-report.md` at the top level of +this project's directory. When the run wired source-map upload, START it with +a **"What you still need to do"** section — numbered, copy-pasteable: + +1. Create a personal API key with the 'Source map upload' preset at + `/settings/user-api-keys` (skip when the credentials handoff says + the key is already written). +2. Add it as the CI secret the wire-ci step referenced, named exactly as in + the pipeline config. +3. Any other manual follow-up the handoffs carry (an untraceable deploy path, + provider-side settings). + +Then cover, briefly and concretely: + +- How uncaught errors reach PostHog now — the capture mechanism and the files + that carry it. +- If the run also installed and initialized the SDK, say so — the user + started this command without PostHog and now has it. +- When source-map upload was wired: the files changed (paths only), the exact + production build command, and that every production build now uploads. +- When it was skipped: one line saying why — readable stack traces on this + platform, or that Astro is not supported by the uploader. An outcome, not an + apology. Say plainly that the build command was left untouched. +- How to verify: trigger any error and look at + `/project//error_tracking`; uploaded symbol sets appear + at `/project//error_tracking/configuration`. + +Never write a secret value into the report — only variable names. Replace +`` and `` from your project context. Give the same +summary in chat. + +## How you know you succeeded + +`posthog-error-tracking-report.md` exists and a user who reads only it knows +how errors reach PostHog, the follow-ups they still owe (the API key and the +CI secret named exactly, when upload was wired), and where in PostHog to see +the first captured exception. diff --git a/context/agents/error-tracking/setup-error-tracking.md b/context/agents/error-tracking/setup-error-tracking.md new file mode 100644 index 00000000..f7ac0ce4 --- /dev/null +++ b/context/agents/error-tracking/setup-error-tracking.md @@ -0,0 +1,96 @@ +--- +type: setup-error-tracking +flow: error-tracking +seed: true +model_pi: openai/gpt-5.6-terra +effort_pi: medium +model_sdk: claude-sonnet-4-6 +effort_sdk: high +skills: [] +allowedTools: [Read, Glob, Grep, posthog_exec] +disallowedTools: [Write, Edit, Bash, complete_task] +dependsOn: [] +--- + +## Goal + +Plan a PostHog Error Tracking setup and seed the task queue. The end state: +errors the app does not catch reach PostHog, and — where the platform ships +minified bundles or stripped binaries — production builds upload the source +maps or debug symbols that make the stack traces readable. + +First establish two facts from the repo: + +**1. Is PostHog already integrated?** Look for `posthog-js` or a server SDK in +the dependency manifests, or a `posthog.init(...)` / snippet in the source. +Check the project state for existing events if the repo is ambiguous. + +**2. Which uploader variant is this project — or none?** Read the manifests +and pick at most one, by this precedence (first match wins): + +- `pubspec.yaml` → `flutter` +- an `.xcodeproj`, `Podfile`, or `Package.swift` → `ios` +- a Gradle build file (`build.gradle`, `build.gradle.kts`, `settings.gradle`) → `android` +- `go.mod` → `go` +- `Cargo.toml` → `rust` +- `astro` in `package.json` dependencies → **none**. Astro is not supported by + the uploader: it inlines scripts below its asset limit into the HTML, so a + build routinely emits a `.map` with no `.js` beside it, and the upload step + then fails the whole build. This rule wins over every `package.json` match + below — an Astro project that also depends on `vite` is still **none**. +- otherwise read `package.json` dependencies, first match wins: + `react-native` → `react-native`; `nuxt` → `nuxt`; `next` → `nextjs`; + `@angular/core` → `angular`; `vite` → `vite`; `webpack` → `webpack`; + `rollup` → `rollup`; `react` → `react`; server-only Node → `node`; + any other browser JS → `web` +- **none** for platforms whose stack traces are already readable: plain + Python (Django, Flask, FastAPI), Ruby, PHP, Elixir, JVM servers, .NET. + Skip the whole upload subgraph for them — a skipped upload on such a + platform is an outcome, not a gap. + +When a variant matched, the uploader skill id is +`error-tracking-upload-source-maps-`. Pass it to the four upload +tasks as `inputs: { skillId: "", displayName: "" }` +so no task re-detects. + +The two facts are independent — settle BOTH before you enqueue anything. +"PostHog is already integrated" answers fact 1 only; it never decides fact 2, +and an already-integrated project still gets the upload subgraph when a +variant matches. A compiled or bundled JS project normally has one: a Node +service built with `tsc` ships minified/compiled output, so it is the `node` +variant, not "none". Only two kinds of project skip the subgraph — the +readable-stack platforms listed above, and Astro. + +Then seed the graph: + +- `install` and `init`, independent of each other — **only when PostHog is + not integrated**. Do not stop on an uninstrumented repo, integrate. +- `capture-exceptions`, after `install` and `init` (with no dependencies when + PostHog was already integrated). +- When an uploader variant matched, add the upload subgraph: + - `credentials`, no dependencies — it stops to ask the user for a personal + API key, so keep it a root task: the prompt reaches the user early while + the code tasks run. + - `configure`, after `capture-exceptions` — build-config changes; it runs + after the code edits so the two never fight over the same files. + - `wire-ci`, after `configure` and `credentials`. + - `test-setup`, after `wire-ci` — offers the user a local end-to-end test + last, once everything is wired. +- `report`, after every other queued task. It writes the handoff last, so it + describes what actually shipped. + +Never plan an identify, capture, dashboard, or session-replay task — this run +sets up error tracking, not the full integration. The minimal SDK footprint +that `install` and `init` leave behind is enough for exceptions to flow. + +## How you know you succeeded + +Every task in the chosen graph is queued with that dependency shape, the four +upload tasks (when queued) share the same `{ skillId, displayName }` inputs, +`report` depends on the rest (directly or transitively), and the first task is +runnable. Your plan states both facts explicitly: whether PostHog was +integrated, and which uploader variant matched — or, when you queue no upload +tasks, why no variant applies: which readable-stack platform this is, or that +Astro is not supported by the uploader. A +plan that never mentions fact 2 is an incomplete plan, not a decision. Keep +labels short — the action in a few words. diff --git a/context/agents/error-tracking/test-setup.md b/context/agents/error-tracking/test-setup.md new file mode 100644 index 00000000..b5d6dfb2 --- /dev/null +++ b/context/agents/error-tracking/test-setup.md @@ -0,0 +1,41 @@ +--- +type: test-setup +flow: error-tracking +label: Offer to test the local setup +model_pi: openai/gpt-5.6-sol +effort_pi: medium +model_sdk: claude-sonnet-4-6 +effort_sdk: high +skills: [] +allowedTools: [Read, Write, Edit, Glob, Grep, Bash, load_skill_menu, install_skill, wizard_ask] +disallowedTools: [enqueue_task] +dependsOn: [wire-ci] +--- + +## Goal + +Offer the user a one-time, end-to-end check that errors reach PostHog with +readable stack traces. Install the skill your task input names (`install_skill` +with the `skillId`) and follow its **"Test the local setup"** step for the +platform-appropriate affordance, the `captureException` shape, the placement, +and the read-before-edit / always-revert rules. + +First ask with `wizard_ask`: +`{ id: "test-affordance", prompt: "Want me to help you test your local setup? I'll add a temporary test button (or route) to your app so you can confirm errors show up in Error Tracking with readable stack traces after your next build. I'll remove it once you've confirmed it works.", kind: "single", options: [{ label: "Yes, help me test it", value: "yes" }, { label: "No, I'll test on my own later", value: "no" }] }` + +- **"no"** (or `wizard_ask` unavailable): do nothing to the code and report this + task done, noting the test was offered and declined. +- **"yes"**: add the affordance per the skill, then pause with a second + `wizard_ask` (id `"test-done"`, a single `Continue (revert test code)` + option) whose prompt gives the build, run, and Error-Tracking-check as + literal numbered steps (build first — it uploads the maps — then trigger the + affordance, then confirm the error resolves to real source in Error + Tracking). After the user continues, REVERT every test edit per the skill's + rules. Never leave the affordance in place, even if the user says it didn't + work — revert first, then carry the failure into your handoff. + +## How you know you succeeded + +Either the user declined and no code changed, or the affordance was added, +tested, and fully reverted. Your handoff says which, and carries any failure +the user reported for the report to surface. diff --git a/context/agents/error-tracking/wire-ci.md b/context/agents/error-tracking/wire-ci.md new file mode 100644 index 00000000..a0ac48f2 --- /dev/null +++ b/context/agents/error-tracking/wire-ci.md @@ -0,0 +1,37 @@ +--- +type: wire-ci +flow: error-tracking +label: Set up CI for automatic uploads +model_pi: openai/gpt-5.6-sol +effort_pi: high +model_sdk: claude-sonnet-4-6 +effort_sdk: high +skills: [] +allowedTools: [Read, Write, Edit, Glob, Grep, load_skill_menu, install_skill] +disallowedTools: [enqueue_task] +dependsOn: [configure, credentials] +--- + +## Goal + +Make the credentials reach the production build wherever it actually runs, so +source maps upload on every deploy — not just on a local build. Install the +skill your task input names (`install_skill` with the `skillId`) and follow its +**"Set up CI for automatic uploads"** step — it owns tracing where the +production build runs and wiring the credentials through every layer, whatever +the CI provider. + +The `configure` and `credentials` handoffs already name the build-config keys +and the exact environment-variable names in use — carry those same names into +the pipeline; do not invent new ones. Trace the deploy path by reading the +project's own files (CI workflows, Dockerfiles, deploy scripts) — never invent +config that is not there. You cannot create the CI secret that holds the API +key; reference it by name and carry that follow-up, plus any deploy path you +could not trace, into your handoff for the report. + +## How you know you succeeded + +The pipeline that runs the production build carries the upload credentials by +the same names the credentials task used, and every secret the user still has +to create is named in your handoff. Your handoff lists the CI files you changed +and every manual follow-up, so the report can hand them to the user. diff --git a/context/skills/error-tracking-upload-source-maps/description.md b/context/skills/error-tracking-upload-source-maps/description.md index bd355029..90078145 100644 --- a/context/skills/error-tracking-upload-source-maps/description.md +++ b/context/skills/error-tracking-upload-source-maps/description.md @@ -34,6 +34,7 @@ Wire source map generation, chunk-ID injection, and upload into your **productio - **Don't ship source maps publicly**: omit `.map` files from the deployed artifact, or use hidden source maps. Uploaded maps live in PostHog, not on your origin. - **Link each release to its commit.** The CLI auto-detects the commit from the CI's git env vars — see "Associate the release with a git commit" for making those reachable in Docker/CI builds. - **Never write a dependency version from memory.** When a variant needs the CLI or a plugin *inside the project* — the JS/web build tools (Node, web, Next.js, React, Angular, Nuxt, Vite, Webpack, Rollup) — install it with the project's package manager pinned to `latest` (`npm install --save-dev @posthog/cli@latest`, `pnpm add -D @posthog/cli@latest`, `yarn add -D @posthog/cli@latest`) and let the manager write the resolved version into `package.json`. A version recalled from memory is usually far behind and silently breaks the commands in this skill — `--dotenv-file`, for one, is rejected outright by 0.5.x. iOS, Android, React Native, Flutter, Go and Rust are the exception: the wizard pre-installs a global `posthog-cli` for those, so add no project dependency for them at all. +- **Match the project's package manager, not the docs'.** Example commands in the docs install with `npm`. Before any install, detect the real manager from the lockfile — `pnpm-lock.yaml` → `pnpm add -D`, `yarn.lock` → `yarn add -D`, `package-lock.json` / none → `npm install --save-dev` (the wizard's `detect_package_manager` tool answers this) — and translate the command. This is load-bearing in monorepos: npm hard-fails on `workspace:*` dependencies with `EUNSUPPORTEDPROTOCOL`, so an npm install copied into a pnpm workspace cannot succeed, and no npm flag fixes it — switch the command to the detected manager instead of retrying. #### Examples - **Node / tsc** Emit maps with embedded sources by setting both in `tsconfig.json`: `"sourceMap": true` and `"inlineSources": true`. Add the CLI to the project with `npm install --save-dev @posthog/cli@latest` (or the project's package manager) so the build script and CI resolve the same binary — never hand-write the version string. Then run `posthog-cli sourcemap process` against the build output dir as a post-build step — it injects chunk IDs and uploads in one pass, and needs the upload credentials (see "Make credentials available at build time").