From f4d18f3938ff0eca22a23304bcf21e3d3b850dac Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:25:04 -0400 Subject: [PATCH 01/10] feat(agents): dashboard subscription + alerts as a subscribe step after dashboard Co-Authored-By: Claude Fable 5 --- .../integration-v2/integrate-posthog.md | 4 +- context/agents/integration-v2/report.md | 2 +- context/agents/integration-v2/subscribe.md | 33 ++++++++++++++ .../integration-v2/subscribe/config.yaml | 11 +++++ .../integration-v2/subscribe/description.md | 45 +++++++++++++++++++ .../integration/references/4-conclude.md | 22 --------- 6 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 context/agents/integration-v2/subscribe.md create mode 100644 context/skills/integration-v2/subscribe/config.yaml create mode 100644 context/skills/integration-v2/subscribe/description.md diff --git a/context/agents/integration-v2/integrate-posthog.md b/context/agents/integration-v2/integrate-posthog.md index c14ce296..39deee64 100644 --- a/context/agents/integration-v2/integrate-posthog.md +++ b/context/agents/integration-v2/integrate-posthog.md @@ -26,7 +26,9 @@ Plan a PostHog integration and seed the task queue with this graph: its tests. - `dashboard`, after `build` — only once the integration is confirmed building, linting, and testing cleanly. -- `report`, after `dashboard` — it writes the setup report last. +- `subscribe`, after `dashboard` — with the user's consent, it subscribes them to + the new dashboard by email and alerts on its highest-signal insights. +- `report`, after `dashboard` and `subscribe` — it writes the setup report last. ## How you know you succeeded diff --git a/context/agents/integration-v2/report.md b/context/agents/integration-v2/report.md index 7c80deed..d7b7d4a7 100644 --- a/context/agents/integration-v2/report.md +++ b/context/agents/integration-v2/report.md @@ -9,7 +9,7 @@ effort_sdk: high skills: [integration-v2-report, integration-v2-notebook, integration-v2-mcp] allowedTools: [Read, Write, Glob, Grep] disallowedTools: [enqueue_task] -dependsOn: [dashboard] +dependsOn: [dashboard, subscribe] --- ## Goal diff --git a/context/agents/integration-v2/subscribe.md b/context/agents/integration-v2/subscribe.md new file mode 100644 index 00000000..51d0d1b5 --- /dev/null +++ b/context/agents/integration-v2/subscribe.md @@ -0,0 +1,33 @@ +--- +type: subscribe +flow: integration-v2 +label: Subscribe the user to the dashboard +model_pi: openai/gpt-5.6-luna +effort_pi: medium +model_sdk: claude-sonnet-4-6 +effort_sdk: high +skills: [integration-v2-subscribe, integration-v2-mcp] +allowedTools: [Read, Glob, Grep] +disallowedTools: [Write, Edit, Bash, enqueue_task] +dependsOn: [dashboard] +--- + +## Goal + +A dashboard nobody revisits is dead weight. Offer to put the one just created in +the user's inbox: a weekly email subscription for the dashboard, plus an alert on +at most two of its insights — only ones whose movement would actually cost the +business something, like a conversion funnel dropping or signups stalling. + +Both are standing side effects beyond the code integration the user asked for, so +ask consent first: say in one line what each is and get a yes or no. If they +decline, skip this whole step and say so. If nothing on the dashboard clearly +deserves an alert, create zero rather than padding to the ceiling. + +## How you know you succeeded + +Either the user declined and nothing was created, or what they agreed to exists in +PostHog: the weekly subscription addressed to their account email, and alerts only +on insights that earn one. Your handoff names each created record with its link — +built with the URL tool, never hand-constructed — which insight each alert watches +and why it was judged highest-signal, or the reason nothing was created. diff --git a/context/skills/integration-v2/subscribe/config.yaml b/context/skills/integration-v2/subscribe/config.yaml new file mode 100644 index 00000000..affe4fc1 --- /dev/null +++ b/context/skills/integration-v2/subscribe/config.yaml @@ -0,0 +1,11 @@ +type: docs-only +template: description.md +description: Subscribe the user to the new dashboard by email and alert on its highest-signal insights +tags: [orchestrator, subscribe] +variants: + - id: all + display_name: PostHog subscribe step + tags: [orchestrator, subscribe] + docs_urls: [] +cli: + role: internal diff --git a/context/skills/integration-v2/subscribe/description.md b/context/skills/integration-v2/subscribe/description.md new file mode 100644 index 00000000..856bb85c --- /dev/null +++ b/context/skills/integration-v2/subscribe/description.md @@ -0,0 +1,45 @@ +# Subscription and alerts for the new dashboard + +This step schedules a real recurring email and enrols the user in alert +notifications — get consent before creating anything, and skip the whole step on a +no. + +On a yes, call `user-get` with uuid `@me` through `posthog_exec` for the current +user's id and email. If no email comes back (service account, unusual SSO), skip +the subscription — don't invent a recipient, note the skip in your handoff — and +still create the alerts, which key off the id, not the email. + +1. **One dashboard subscription (`subscriptions-create`).** Weekly email digest of + the dashboard just created: `target_type: "email"`, `target_value` set to the + user's email from `user-get`, `dashboard` set to the new dashboard id, + `dashboard_export_insights` set to up to 6 of its insight ids (or fewer if the + dashboard has fewer), `frequency: "weekly"`, `interval: 1` (every 1 week), + `start_date` set to now. Leave `summary_enabled` off — enabling AI summaries + needs its own separate human OK that this consent didn't cover. +2. **One or two insight alerts (`alert-create`)**, only on the insight(s) that + would actually cost the business something if they moved the wrong way — a + conversion funnel dropping, a churn/drop-off event spiking, signups stalling. + Skip "nice to watch" insights (e.g. a raw pageview count), and if nothing on + the dashboard clearly qualifies, create zero. For a funnel step, use + `condition: { type: "relative_decrease" }` with a `FunnelsAlertConfig`; for a + trend that should stay above/below a bound, use a `TrendsAlertConfig` with + `threshold.configuration.bounds`. Set `subscribed_users` to `[]` (the integer id, not the uuid) and + `calculation_interval: "daily"` unless the insight's own interval argues for + something coarser. + +The create calls return the new records but not a link, so build each URL with +`generate-app-url` from the ids you just got back — never hand-construct these +paths. For the subscription, call `generate-app-url` with `url` set to +`/dashboard/{id}/subscriptions/{subscriptionId}` and `params` +`{ "id": , "subscriptionId": }`. For +each alert, call `generate-app-url` with `url` set to +`/insights/{insightShortId}/alerts` and `params` +`{ "insightShortId": }`. + +In your handoff, briefly explain what a subscription is (a recurring email +snapshot of the dashboard) and what an alert is (an email the moment a specific +metric crosses a threshold), give the link for each created record, and name which +insight(s) got an alert and why they were judged the highest-signal ones — the +report step relays this to the user, including a reminder to check the recipient +and cadence defaults. diff --git a/context/skills/integration/references/4-conclude.md b/context/skills/integration/references/4-conclude.md index 2fe51d01..61f21afb 100644 --- a/context/skills/integration/references/4-conclude.md +++ b/context/skills/integration/references/4-conclude.md @@ -70,21 +70,6 @@ Valid `trendsFilter.display` values are `ActionsLineGraph`, `ActionsBar`, `Actio Once the dashboard exists, emit its URL on its own line in your assistant message using this exact marker: `[DASHBOARD_URL] `. The wizard parses this marker from your visible message and surfaces the link in the success summary. Mentioning the URL only in thinking or in prose without the marker means the link is dropped. -### Set up a subscription and alerts so the dashboard reaches an inbox - -This step schedules a real recurring email and enrols the user in alert notifications — standing side effects beyond the code integration they asked for, so get consent first. - -**Ask before creating anything.** Tell the user you'd like to set up a weekly email digest of the new dashboard plus up to two alerts on its highest-signal insights, say in one line what each is, and get a yes/no. If they decline, skip this whole section. - -On a yes, call `user-get` with uuid `@me` for the current user's id and email. If no email comes back (service account, unusual SSO), skip the subscription — don't invent a recipient, note the skip in the report — and still create the alerts, which key off the id, not the email. - -1. **One dashboard subscription (`subscriptions-create`).** Weekly email digest of the dashboard just created: `target_type: "email"`, `target_value` set to the user's email from `user-get`, `dashboard` set to the new dashboard id, `dashboard_export_insights` set to up to 6 of its insight ids (or fewer if the dashboard has fewer), `frequency: "weekly"`, `interval: 1` (every 1 week), `start_date` set to now. Leave `summary_enabled` off — enabling AI summaries needs its own separate human OK that this consent didn't cover. -2. **One or two insight alerts (`alert-create`)**, only on the insight(s) that would actually cost the business something if they moved the wrong way — a conversion funnel dropping, a churn/drop-off event spiking, signups stalling. Skip "nice to watch" insights (e.g. a raw pageview count), and if nothing on the dashboard clearly qualifies, create zero rather than padding to the ceiling. For a funnel step, use `condition: { type: "relative_decrease" }` with a `FunnelsAlertConfig`; for a trend that should stay above/below a bound, use a `TrendsAlertConfig` with `threshold.configuration.bounds`. Set `subscribed_users` to `[]` (the integer id, not the uuid) and `calculation_interval: "daily"` unless the insight's own interval argues for something coarser. - -The create calls return the new records but not a link, so build each URL with `generate-app-url` from the ids you just got back — never hand-construct these paths. For the subscription, `call generate-app-url` with `url` set to `/dashboard/{id}/subscriptions/{subscriptionId}` and `params` `{ "id": , "subscriptionId": }`. For each alert, `call generate-app-url` with `url` set to `/insights/{insightShortId}/alerts` and `params` `{ "insightShortId": }`. - -When writing the setup report, briefly explain what a subscription is (a recurring email snapshot of the dashboard) and what an alert is (a one-off email the moment a specific metric crosses a threshold), and name which insight(s) got an alert and why they were judged the highest-signal ones. - Search for a file called `.posthog-events.json` and read it for available events. Do not spawn subagents. @@ -104,10 +89,6 @@ We've built some insights and a dashboard for you to keep an eye on user behavio [links] -[one line explaining the dashboard subscription: what it is, cadence, and which email it goes to, with a link to it in PostHog] - -[one line per alert: which insight it watches, the condition, that it emails on breach, why that metric moving is worth caring about, and a link to it in PostHog] - ## Verify before merging [checklist] @@ -126,7 +107,6 @@ For the "Verify before merging" checklist, write GitHub-style checkboxes (`- [ ] - If this integration ships a minified production browser bundle (most SPA/SSR web frameworks — e.g. Next.js, Nuxt, SvelteKit, Astro, Vite-based apps): "Wire source-map upload (`posthog-cli sourcemap` or your bundler's upload step) into CI so production stack traces de-minify." - If LLM analytics was set up in this run: "Trigger the LLM call path(s) you instrumented and confirm `$ai_generation` events appear in PostHog AI Observability." - If the app has user auth and an `identify` call was added: "Confirm the returning-visitor path also calls `identify` — a handler that only identifies on fresh login can leave returning sessions on anonymous distinct IDs." -- Always (if a subscription or alert was created): "Check the dashboard subscription and alert(s) went to the right inbox and cadence — the wizard defaulted to your account email and a weekly/daily schedule." Do not invent items beyond what applies. If only the two "Always" items apply, the checklist is just those two. @@ -139,7 +119,5 @@ Upon completion, update `.posthog-events.json` so it matches the events you actu Status to report in this phase: - Configured dashboard: [insert PostHog dashboard URL] -- Configured dashboard subscription: [recipient email, frequency] -- Configured alert(s): [insight name(s), condition] - Created setup report: [insert full local file path] - Created notebook: [insert PostHog notebook URL] From 1d0eb4ff68cce65490bbcb7c4a53c6500ad5db45 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:33:54 -0400 Subject: [PATCH 02/10] refactor(skills): dashboard-subscriptions as a general skill, consent ask in the agent Co-Authored-By: Claude Fable 5 --- context/agents/integration-v2/subscribe.md | 26 +++++------ .../dashboard-subscriptions/config.yaml | 9 ++++ .../dashboard-subscriptions/description.md | 44 ++++++++++++++++++ .../integration-v2/subscribe/config.yaml | 11 ----- .../integration-v2/subscribe/description.md | 45 ------------------- node_modules | 1 + 6 files changed, 67 insertions(+), 69 deletions(-) create mode 100644 context/skills/dashboard-subscriptions/config.yaml create mode 100644 context/skills/dashboard-subscriptions/description.md delete mode 100644 context/skills/integration-v2/subscribe/config.yaml delete mode 100644 context/skills/integration-v2/subscribe/description.md create mode 120000 node_modules diff --git a/context/agents/integration-v2/subscribe.md b/context/agents/integration-v2/subscribe.md index 51d0d1b5..66d9d8a9 100644 --- a/context/agents/integration-v2/subscribe.md +++ b/context/agents/integration-v2/subscribe.md @@ -6,7 +6,7 @@ model_pi: openai/gpt-5.6-luna effort_pi: medium model_sdk: claude-sonnet-4-6 effort_sdk: high -skills: [integration-v2-subscribe, integration-v2-mcp] +skills: [dashboard-subscriptions, integration-v2-mcp] allowedTools: [Read, Glob, Grep] disallowedTools: [Write, Edit, Bash, enqueue_task] dependsOn: [dashboard] @@ -14,20 +14,20 @@ dependsOn: [dashboard] ## Goal -A dashboard nobody revisits is dead weight. Offer to put the one just created in -the user's inbox: a weekly email subscription for the dashboard, plus an alert on -at most two of its insights — only ones whose movement would actually cost the -business something, like a conversion funnel dropping or signups stalling. +A dashboard nobody revisits is dead weight. Set up a weekly email subscription for +the dashboard the previous step created, plus up to two alerts on its +highest-signal insights, so the wizard's output reaches an inbox and the metrics +that actually matter get flagged. -Both are standing side effects beyond the code integration the user asked for, so -ask consent first: say in one line what each is and get a yes or no. If they -decline, skip this whole step and say so. If nothing on the dashboard clearly -deserves an alert, create zero rather than padding to the ceiling. +This step schedules a real recurring email and enrols the user in alert +notifications — standing side effects beyond the code integration they asked for, +so get consent first. Ask before creating anything: tell the user you'd like to +set up a weekly email digest of the new dashboard plus up to two alerts on its +highest-signal insights, say in one line what each is, and get a yes/no. If they +decline, skip this whole step. ## How you know you succeeded Either the user declined and nothing was created, or what they agreed to exists in -PostHog: the weekly subscription addressed to their account email, and alerts only -on insights that earn one. Your handoff names each created record with its link — -built with the URL tool, never hand-constructed — which insight each alert watches -and why it was judged highest-signal, or the reason nothing was created. +PostHog with a link to each created record in your handoff, plus which insight(s) +got an alert and why — the report step relays this to the user. diff --git a/context/skills/dashboard-subscriptions/config.yaml b/context/skills/dashboard-subscriptions/config.yaml new file mode 100644 index 00000000..62b8cc9f --- /dev/null +++ b/context/skills/dashboard-subscriptions/config.yaml @@ -0,0 +1,9 @@ +type: skill +template: description.md +description: Set up a dashboard email subscription and alerts on its highest-signal insights +tags: [dashboard, subscriptions, alerts] +variants: + - id: all + display_name: Dashboard subscriptions and alerts + tags: [dashboard, subscriptions, alerts] + docs_urls: [] diff --git a/context/skills/dashboard-subscriptions/description.md b/context/skills/dashboard-subscriptions/description.md new file mode 100644 index 00000000..593ccfb0 --- /dev/null +++ b/context/skills/dashboard-subscriptions/description.md @@ -0,0 +1,44 @@ +# Set up a subscription and alerts so a dashboard reaches an inbox + +This sets up a real recurring email and enrols the user in alert notifications for +a target dashboard. + +Call `user-get` with uuid `@me` for the current user's id and email. If no email +comes back (service account, unusual SSO), skip the subscription — don't invent a +recipient, note the skip — and still create the alerts, which key off the id, not +the email. + +1. **One dashboard subscription (`subscriptions-create`).** Weekly email digest of + the target dashboard: `target_type: "email"`, `target_value` set to the user's + email from `user-get`, `dashboard` set to the dashboard id, + `dashboard_export_insights` set to up to 6 of its insight ids (or fewer if the + dashboard has fewer), `frequency: "weekly"`, `interval: 1` (every 1 week), + `start_date` set to now. Leave `summary_enabled` off — enabling AI summaries + needs its own separate human OK. +2. **One or two insight alerts (`alert-create`)**, only on the insight(s) that + would actually cost the business something if they moved the wrong way — a + conversion funnel dropping, a churn/drop-off event spiking, signups stalling. + Skip "nice to watch" insights (e.g. a raw pageview count), and if nothing on + the dashboard clearly qualifies, create zero rather than padding to the + ceiling. For a funnel step, use `condition: { type: "relative_decrease" }` with + a `FunnelsAlertConfig`; for a trend that should stay above/below a bound, use a + `TrendsAlertConfig` with `threshold.configuration.bounds`. Set + `subscribed_users` to `[]` (the integer id, not + the uuid) and `calculation_interval: "daily"` unless the insight's own interval + argues for something coarser. + +The create calls return the new records but not a link, so build each URL with +`generate-app-url` from the ids you just got back — never hand-construct these +paths. For the subscription, call `generate-app-url` with `url` set to +`/dashboard/{id}/subscriptions/{subscriptionId}` and `params` +`{ "id": , "subscriptionId": }`. For +each alert, call `generate-app-url` with `url` set to +`/insights/{insightShortId}/alerts` and `params` +`{ "insightShortId": }`. + +When writing up what was created, briefly explain what a subscription is (a +recurring email snapshot of the dashboard) and what an alert is (a one-off email +the moment a specific metric crosses a threshold), and name which insight(s) got +an alert and why they were judged the highest-signal ones. Remind the user to +check the subscription and alert(s) went to the right inbox and cadence — the +defaults are their account email and a weekly/daily schedule. diff --git a/context/skills/integration-v2/subscribe/config.yaml b/context/skills/integration-v2/subscribe/config.yaml deleted file mode 100644 index affe4fc1..00000000 --- a/context/skills/integration-v2/subscribe/config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -type: docs-only -template: description.md -description: Subscribe the user to the new dashboard by email and alert on its highest-signal insights -tags: [orchestrator, subscribe] -variants: - - id: all - display_name: PostHog subscribe step - tags: [orchestrator, subscribe] - docs_urls: [] -cli: - role: internal diff --git a/context/skills/integration-v2/subscribe/description.md b/context/skills/integration-v2/subscribe/description.md deleted file mode 100644 index 856bb85c..00000000 --- a/context/skills/integration-v2/subscribe/description.md +++ /dev/null @@ -1,45 +0,0 @@ -# Subscription and alerts for the new dashboard - -This step schedules a real recurring email and enrols the user in alert -notifications — get consent before creating anything, and skip the whole step on a -no. - -On a yes, call `user-get` with uuid `@me` through `posthog_exec` for the current -user's id and email. If no email comes back (service account, unusual SSO), skip -the subscription — don't invent a recipient, note the skip in your handoff — and -still create the alerts, which key off the id, not the email. - -1. **One dashboard subscription (`subscriptions-create`).** Weekly email digest of - the dashboard just created: `target_type: "email"`, `target_value` set to the - user's email from `user-get`, `dashboard` set to the new dashboard id, - `dashboard_export_insights` set to up to 6 of its insight ids (or fewer if the - dashboard has fewer), `frequency: "weekly"`, `interval: 1` (every 1 week), - `start_date` set to now. Leave `summary_enabled` off — enabling AI summaries - needs its own separate human OK that this consent didn't cover. -2. **One or two insight alerts (`alert-create`)**, only on the insight(s) that - would actually cost the business something if they moved the wrong way — a - conversion funnel dropping, a churn/drop-off event spiking, signups stalling. - Skip "nice to watch" insights (e.g. a raw pageview count), and if nothing on - the dashboard clearly qualifies, create zero. For a funnel step, use - `condition: { type: "relative_decrease" }` with a `FunnelsAlertConfig`; for a - trend that should stay above/below a bound, use a `TrendsAlertConfig` with - `threshold.configuration.bounds`. Set `subscribed_users` to `[]` (the integer id, not the uuid) and - `calculation_interval: "daily"` unless the insight's own interval argues for - something coarser. - -The create calls return the new records but not a link, so build each URL with -`generate-app-url` from the ids you just got back — never hand-construct these -paths. For the subscription, call `generate-app-url` with `url` set to -`/dashboard/{id}/subscriptions/{subscriptionId}` and `params` -`{ "id": , "subscriptionId": }`. For -each alert, call `generate-app-url` with `url` set to -`/insights/{insightShortId}/alerts` and `params` -`{ "insightShortId": }`. - -In your handoff, briefly explain what a subscription is (a recurring email -snapshot of the dashboard) and what an alert is (an email the moment a specific -metric crosses a threshold), give the link for each created record, and name which -insight(s) got an alert and why they were judged the highest-signal ones — the -report step relays this to the user, including a reminder to check the recipient -and cadence defaults. diff --git a/node_modules b/node_modules new file mode 120000 index 00000000..9016afd7 --- /dev/null +++ b/node_modules @@ -0,0 +1 @@ +/Users/vincent/work-code/context-mill/node_modules \ No newline at end of file From f2dd0622ca5af59e568e4388c13394a3498df94a Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:34:10 -0400 Subject: [PATCH 03/10] chore: drop stray node_modules symlink from the tree Co-Authored-By: Claude Fable 5 --- .gitignore | 1 + node_modules | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 120000 node_modules diff --git a/.gitignore b/.gitignore index 05899492..87f2c390 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,4 @@ posthog-audit-report.md # Local scratch dirs scratch/ +node_modules diff --git a/node_modules b/node_modules deleted file mode 120000 index 9016afd7..00000000 --- a/node_modules +++ /dev/null @@ -1 +0,0 @@ -/Users/vincent/work-code/context-mill/node_modules \ No newline at end of file From 4695cdeef184b2d8a0b0b76c8cb5c2b9477a38a8 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:35:48 -0400 Subject: [PATCH 04/10] chore: keep the symlink-covering node_modules rule beside the directory rule Co-Authored-By: Claude Fable 5 --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 87f2c390..debc6bba 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ Thumbs.db # Dependencies (covered by individual projects, but included for safety) node_modules/ +node_modules .pnp .pnp.* @@ -92,4 +93,3 @@ posthog-audit-report.md # Local scratch dirs scratch/ -node_modules From 6696ceac2730e08e9e18f9e264f9b699ef73928a Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:36:25 -0400 Subject: [PATCH 05/10] chore: drop the gitignore change Co-Authored-By: Claude Fable 5 --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index debc6bba..05899492 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,6 @@ Thumbs.db # Dependencies (covered by individual projects, but included for safety) node_modules/ -node_modules .pnp .pnp.* From 39e00a7fd2d19a9dee280d8e79ddb76ba4aa5960 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:39:59 -0400 Subject: [PATCH 06/10] =?UTF-8?q?feat(skills):=20wizard-ask=20=E2=80=94=20?= =?UTF-8?q?a=20generic=20how-to-ask=20skill=20for=20steps=20that=20need=20?= =?UTF-8?q?consent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- context/agents/integration-v2/subscribe.md | 2 +- context/skills/wizard-ask/config.yaml | 9 +++++ context/skills/wizard-ask/description.md | 46 ++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 context/skills/wizard-ask/config.yaml create mode 100644 context/skills/wizard-ask/description.md diff --git a/context/agents/integration-v2/subscribe.md b/context/agents/integration-v2/subscribe.md index 66d9d8a9..1e553ebd 100644 --- a/context/agents/integration-v2/subscribe.md +++ b/context/agents/integration-v2/subscribe.md @@ -6,7 +6,7 @@ model_pi: openai/gpt-5.6-luna effort_pi: medium model_sdk: claude-sonnet-4-6 effort_sdk: high -skills: [dashboard-subscriptions, integration-v2-mcp] +skills: [dashboard-subscriptions, wizard-ask, integration-v2-mcp] allowedTools: [Read, Glob, Grep] disallowedTools: [Write, Edit, Bash, enqueue_task] dependsOn: [dashboard] diff --git a/context/skills/wizard-ask/config.yaml b/context/skills/wizard-ask/config.yaml new file mode 100644 index 00000000..6febbbe0 --- /dev/null +++ b/context/skills/wizard-ask/config.yaml @@ -0,0 +1,9 @@ +type: skill +template: description.md +description: Ask the user structured questions through the wizard and act on their answers +tags: [wizard, ask] +variants: + - id: all + display_name: Asking the user through the wizard + tags: [wizard, ask] + docs_urls: [] diff --git a/context/skills/wizard-ask/description.md b/context/skills/wizard-ask/description.md new file mode 100644 index 00000000..a85d0540 --- /dev/null +++ b/context/skills/wizard-ask/description.md @@ -0,0 +1,46 @@ +# Asking the user through the wizard + +`wizard_ask` puts structured questions in front of the user in the wizard's own UI +and waits for their answers. Use it whenever you would otherwise inline a question +in your text output — consent for a side effect, a choice between options, a value +only the user knows. + +One call carries 1–8 questions: + +```json +{ + "questions": [ + { + "id": "subscribe", + "prompt": "Set up a weekly email digest of the new dashboard?", + "kind": "single", + "options": [ + { "label": "Yes, email me weekly", "value": "yes" }, + { "label": "No thanks", "value": "no" } + ] + } + ] +} +``` + +- `id` — unique per question; answers come back keyed by it. +- `kind` — `single` (pick one), `multi` (pick several), `text` (free entry). + `single` and `multi` require at least one `{ label, value }` option. +- `required` — defaults to true. +- `sensitive` — `text` only. The answer goes into the wizard's secret vault and + you receive `{ secretRef: "secret:..." }` instead of the raw string. Only + wizard tools that accept refs (e.g. `set_env_values`) can resolve it — other + MCP tools reject it, so write a secret to the env first if another tool needs it. + +Batch related questions into a single call rather than asking one at a time — +sequential calls are for questions that genuinely depend on earlier answers, and +the wizard nudges then caps agents that dribble questions out. A cancelled or +timed-out overlay means the user declined: fall back gracefully — sensible +defaults, a deep link, or skipping the optional work with a note — and don't +re-ask. In a non-interactive run the tool returns an error saying so; do what it +instructs (proceed on defaults, or abort if the answer was truly required). + +For consent to a side effect (an email, a schedule, anything that outlives the +run): one `single` yes/no question, the prompt saying in one line what you want to +create and what it does. A decline means skip that work entirely and say so in +what you hand off — not ask again in different words. From 19d63e6424fefc42a813d14b132c25337aa4cbde Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:42:05 -0400 Subject: [PATCH 07/10] =?UTF-8?q?fix(skills):=20wizard-ask=20stays=20gener?= =?UTF-8?q?ic=20=E2=80=94=20mechanics=20only,=20what-to-ask=20lives=20in?= =?UTF-8?q?=20agents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- context/skills/wizard-ask/description.md | 29 +++++++++++------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/context/skills/wizard-ask/description.md b/context/skills/wizard-ask/description.md index a85d0540..dae19ac9 100644 --- a/context/skills/wizard-ask/description.md +++ b/context/skills/wizard-ask/description.md @@ -2,8 +2,7 @@ `wizard_ask` puts structured questions in front of the user in the wizard's own UI and waits for their answers. Use it whenever you would otherwise inline a question -in your text output — consent for a side effect, a choice between options, a value -only the user knows. +in your text output. One call carries 1–8 questions: @@ -11,14 +10,15 @@ One call carries 1–8 questions: { "questions": [ { - "id": "subscribe", - "prompt": "Set up a weekly email digest of the new dashboard?", + "id": "region", + "prompt": "Which PostHog region is this project in?", "kind": "single", "options": [ - { "label": "Yes, email me weekly", "value": "yes" }, - { "label": "No thanks", "value": "no" } + { "label": "US cloud", "value": "us" }, + { "label": "EU cloud", "value": "eu" } ] - } + }, + { "id": "team_name", "prompt": "What should the team be called?", "kind": "text" } ] } ``` @@ -26,7 +26,8 @@ One call carries 1–8 questions: - `id` — unique per question; answers come back keyed by it. - `kind` — `single` (pick one), `multi` (pick several), `text` (free entry). `single` and `multi` require at least one `{ label, value }` option. -- `required` — defaults to true. +- `required` — defaults to true. Mark a question `required: false` when a blank + answer is acceptable and you have a sensible default to fall back on. - `sensitive` — `text` only. The answer goes into the wizard's secret vault and you receive `{ secretRef: "secret:..." }` instead of the raw string. Only wizard tools that accept refs (e.g. `set_env_values`) can resolve it — other @@ -34,13 +35,9 @@ One call carries 1–8 questions: Batch related questions into a single call rather than asking one at a time — sequential calls are for questions that genuinely depend on earlier answers, and -the wizard nudges then caps agents that dribble questions out. A cancelled or -timed-out overlay means the user declined: fall back gracefully — sensible -defaults, a deep link, or skipping the optional work with a note — and don't +the wizard nudges then caps agents that dribble questions out. + +A cancelled or timed-out overlay means the user declined: fall back gracefully — +your defaults, a deep link, or skipping the optional work with a note — and don't re-ask. In a non-interactive run the tool returns an error saying so; do what it instructs (proceed on defaults, or abort if the answer was truly required). - -For consent to a side effect (an email, a schedule, anything that outlives the -run): one `single` yes/no question, the prompt saying in one line what you want to -create and what it does. A decline means skip that work entirely and say so in -what you hand off — not ask again in different words. From 79cf6a1703469f6817b0fc34aba20cd313d0739b Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:43:38 -0400 Subject: [PATCH 08/10] fix(skills): placeholder example in wizard-ask so nothing reads as a question to ask Co-Authored-By: Claude Fable 5 --- context/skills/wizard-ask/description.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/context/skills/wizard-ask/description.md b/context/skills/wizard-ask/description.md index dae19ac9..3b1fc15d 100644 --- a/context/skills/wizard-ask/description.md +++ b/context/skills/wizard-ask/description.md @@ -10,15 +10,15 @@ One call carries 1–8 questions: { "questions": [ { - "id": "region", - "prompt": "Which PostHog region is this project in?", + "id": "", + "prompt": "", "kind": "single", "options": [ - { "label": "US cloud", "value": "us" }, - { "label": "EU cloud", "value": "eu" } + { "label": "", "value": "" }, + { "label": "", "value": "" } ] }, - { "id": "team_name", "prompt": "What should the team be called?", "kind": "text" } + { "id": "", "prompt": "", "kind": "text" } ] } ``` From 9f2d01ce6bc255d670b6340daa03e2e36f04193a Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:53:29 -0400 Subject: [PATCH 09/10] fix(agents): subscribe asks the exact consent question Co-Authored-By: Claude Fable 5 --- context/agents/integration-v2/subscribe.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/context/agents/integration-v2/subscribe.md b/context/agents/integration-v2/subscribe.md index 1e553ebd..35456f67 100644 --- a/context/agents/integration-v2/subscribe.md +++ b/context/agents/integration-v2/subscribe.md @@ -20,14 +20,14 @@ highest-signal insights, so the wizard's output reaches an inbox and the metrics that actually matter get flagged. This step schedules a real recurring email and enrols the user in alert -notifications — standing side effects beyond the code integration they asked for, -so get consent first. Ask before creating anything: tell the user you'd like to -set up a weekly email digest of the new dashboard plus up to two alerts on its -highest-signal insights, say in one line what each is, and get a yes/no. If they -decline, skip this whole step. +notifications, standing side effects beyond the code integration they asked for, +so get consent before creating anything. Ask exactly this: "Want a weekly email +digest of your new dashboard, plus alerts on up to two of its most important +insights that email you when they move the wrong way?" If they decline, skip this +whole step. ## How you know you succeeded Either the user declined and nothing was created, or what they agreed to exists in PostHog with a link to each created record in your handoff, plus which insight(s) -got an alert and why — the report step relays this to the user. +got an alert and why. The report step relays this to the user. From 8574afde386ec03c24ba7ae399d1ab958c96f02f Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Mon, 20 Jul 2026 21:55:44 -0400 Subject: [PATCH 10/10] fix(agents): the consent question gets its own section Co-Authored-By: Claude Fable 5 --- context/agents/integration-v2/subscribe.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/context/agents/integration-v2/subscribe.md b/context/agents/integration-v2/subscribe.md index 35456f67..31df1ce5 100644 --- a/context/agents/integration-v2/subscribe.md +++ b/context/agents/integration-v2/subscribe.md @@ -20,11 +20,17 @@ highest-signal insights, so the wizard's output reaches an inbox and the metrics that actually matter get flagged. This step schedules a real recurring email and enrols the user in alert -notifications, standing side effects beyond the code integration they asked for, -so get consent before creating anything. Ask exactly this: "Want a weekly email -digest of your new dashboard, plus alerts on up to two of its most important -insights that email you when they move the wrong way?" If they decline, skip this -whole step. +notifications, standing side effects beyond the code integration they asked for. +Get consent before creating anything. + +## The question + +Ask exactly this, then follow the answer: + +- "Want a weekly email digest of your new dashboard, plus alerts on up to two of + its most important insights that email you when they move the wrong way?" +- Yes: create the subscription and the alerts. +- No: skip this whole step and create nothing. ## How you know you succeeded