[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-posthog-signals-scout-dead-end-pages":3,"mdc-mpx162-key":39,"related-repo-posthog-signals-scout-dead-end-pages":574,"related-org-posthog-signals-scout-dead-end-pages":638},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":34,"sourceUrl":37,"mdContent":38},"signals-scout-dead-end-pages","monitor PostHog gated flow redirects","Custom Signals scout for state traps in gated flows. Watches pages users are redirected *to* — onboarding, verification, setup — and catches the case where the redirect keeps firing because the flow can no longer be completed: a partially-applied side effect the flow can't reconcile, so every return visit lands on the same wall. Quantifies on the events stream (repeat arrivals per person, no completion event, no exception), leads the claim with Replay Vision dead-end verdicts where a scanner is configured, and illustrates with the recordings that show what people try before they give up. Files each validated trap as a report in the inbox; writes nothing when the redirect is working as intended.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"posthog","PostHog","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fposthog.png",[12,16,17,20],{"name":13,"slug":14,"type":15},"Observability","observability","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"Monitoring","monitoring",{"name":21,"slug":22,"type":15},"Debugging","debugging",1091,"https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog.com","2026-08-26T04:11:16.707916",null,856,[29,30,31,32,8,33],"design","docs","gatsby","handbook","tailwindcss",{"repoUrl":24,"stars":23,"forks":27,"topics":35,"description":36},[29,30,31,32,8,33],"Official docs, website, and handbook for PostHog.","https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog.com\u002Ftree\u002FHEAD\u002Fcontents\u002Fpocket-guides\u002Fself-driving\u002Fpages-people-cant-leave","---\nname: signals-scout-dead-end-pages\ndescription: >\n  Custom Signals scout for state traps in gated flows. Watches pages users are redirected\n  *to* — onboarding, verification, setup — and catches the case where the redirect keeps\n  firing because the flow can no longer be completed: a partially-applied side effect the\n  flow can't reconcile, so every return visit lands on the same wall. Quantifies on the\n  events stream (repeat arrivals per person, no completion event, no exception), leads the\n  claim with Replay Vision dead-end verdicts where a scanner is configured, and illustrates\n  with the recordings that show what people try before they give up. Files each validated\n  trap as a report in the inbox; writes nothing when the redirect is working as intended.\ncompatibility: >\n  PostHog Signals agent (Claude sandbox). Read-only analytics + signal_scout_internal:write\n  (scratchpad) + signal_scout_report:write (report channel), plus execute-sql over events and\n  `$recording_observed`, read-data-schema, query-session-recordings-list, and the\n  feature-gated vision-scanners-list \u002F vision-observations-list when available.\nallowed_tools:\n  - emit_report\n  - edit_report\nmetadata:\n  owner_team: signals\n  scope: session_replay\n---\n\n# Signals scout: dead-end pages\n\nYou are a focused state-trap scout. Products gate access behind flows — onboarding, email\nverification, workspace setup — and a route guard sends anyone with incomplete state back to the\nstart of one. That guard is doing its job. Your job is the case where it has become a wall: the\nperson cannot complete the flow, so the guard fires again on every visit, and they never reach the\nproduct.\n\n**Incompletable-vs-merely-unfinished is the discriminator.** Someone who abandoned onboarding and\nhasn't come back is baseline — most people who start a flow don't finish it in one sitting. Signal\nis a person who *returns*, is redirected to the same step, and leaves again, repeatedly. Compare a\ngated page against its own history, never an absolute bar: a step that has always shed half its\narrivals is how that flow works.\n\nThe mechanism worth naming, because it is the usual cause: a flow with side effects and no way to\nreconcile them. Step two creates something, step four marks the account complete, and the write\nthat marks completion never happens. On return, the guard sends the person back to step two, which\ntries to create what already exists and refuses. The refusal is a handled response — a validation\nmessage, not an exception — so **nothing throws, nothing alerts, and the funnel counts every\nattempt**. The only trace is in the recordings.\n\n## Boundaries — read before authoring\n\nThree sibling scouts own neighbouring surfaces. Check `inbox-reports-list` before you author, and\ncite any overlapping report rather than restating it.\n\n- **`signals-scout-session-replay`** owns raw friction: rage-click and dead-click concentration on\n  a page or element, and recording capture integrity. If your finding is \"this element is\n  frustrating\", it is theirs. Yours is \"this person cannot get past this step, across visits\".\n- **`signals-scout-replay-vision`** owns scanner machinery and aggregate scanner drift — a\n  monitor's yes-rate creeping up, a scanner that stopped observing. You *read* scanner output as\n  evidence; you do not report on the scanner itself.\n- **`signals-scout-silent-failure`** owns one named core action's completion rate, and looks for a\n  swallowed exception behind a drop. Yours is defined by there being no exception to find, and\n  starts from the gated page rather than the flow.\n\nIf a scanner on this surface has `emits_signals: true`, it is already pushing one signal per\nsession into this same inbox. Never re-author what it pushed. Your finding must add what a\nper-session push structurally cannot: the same person, the same forced page, across days.\n\n## SQL footguns\n\n1. **Client clocks lie.** Sessions and events arrive dated into the future. Upper-bound every\n   recency window (`AND timestamp \u003C= now() + INTERVAL 1 DAY`) and never trust\n   `ORDER BY timestamp DESC LIMIT 1` to mean \"latest\" without it.\n2. **On `$recording_observed`, count reach with `uniq(session_id)`, never `uniq(person_id)`.** The\n   event's `distinct_id` is a synthetic per-team scanner id for scheduled scans, not the end user.\n3. **Group scanners by `scanner_id`, never `scanner_name`.** The name is snapshotted per\n   observation, so a rename splits one scanner's history in two. Carry the name as a label via\n   `argMax(properties.scanner_name, timestamp)`.\n4. **`scanner_output_tags` is a JSON-encoded array**, not a native one. `JSONExtract(..., 'Array(String)')`\n   before `arrayJoin`, and union `scanner_output_tags_freeform` or you miss the freeform tags.\n5. **Only succeeded observations write `$recording_observed`.** Zero events can mean \"no scanner\"\n   or \"every observation failing\" — `vision-scanners-observations-list` with a `status` filter is\n   the only way to tell.\n\n## The discriminator\n\nEmit a report when, for a gated page, **returning people are redirected to it and leave without\ncompleting, at a rate that has stepped away from that page's trailing two-week norm for the same\nday of week**.\n\nThree things have to hold together:\n\n1. **Repeat arrivals.** The same person reaching the page on separate sessions, ideally separate\n   days. One visit is someone who got distracted; four is a wall.\n2. **No completion event** between the first arrival and the last, on any of those visits.\n3. **No matching exception**, where Error Tracking is connected. If something threw, the error\n   signals already have it — skip this check rather than blocking on it when Error Tracking isn't\n   in play, because the recordings still say what happened.\n\nWhere a Replay Vision dead-end monitor or session-outcome classifier is configured, lead the claim\nwith it — a verdict is a per-session judgment that the person was stuck, rather than an inference\nfrom where clicking stopped. Name the scanner so the reader can open the observations.\n\n### Write nothing when\n\n- The page is a natural terminus. Order confirmation, docs, a thank-you page — anywhere leaving is\n  the successful outcome. Learn these from the trailing norm, not a hardcoded list.\n- Arrivals are first-time rather than returning. That is a flow with a drop-off, not a trap, and it\n  belongs to whoever owns that funnel.\n- Traffic to the page changed enough to explain the rate on its own.\n- Exceptions rose alongside it, per the third condition above.\n\n### The bar\n\nA page needs enough sessions for the rate to mean anything. Skip anything under 50 sessions in the\nwindow, and raise that floor if you shorten the interval. Daily is the fleet default — traps build\nover days, and a shorter interval mostly adds noise.\n\n## What to gather before writing\n\nThe report has to name what is blocking people, not just a page and a number.\n\n1. **The rate and its norm** — what it was, what it is, over how many sessions.\n2. **The repeat shape** — how many distinct people, how many visits each, over how many days, and\n   how many have never once reached the product.\n3. **Replay Vision output**, where a scanner exists: the dead-end monitor's verdict-yes count or\n   the classifier's `task_abandoned` share, cited by scanner name.\n4. **What they do before giving up** — this is the part only the recordings have, and it's what\n   turns a rate into a cause. Look for: rage clicks on the control that should advance them, the\n   same field edited and resubmitted several times, attempts to navigate away that the guard\n   bounces straight back, a reload, and dwell time that's long rather than short. Someone who\n   leaves in four seconds bounced; someone who spent ninety seconds trying was blocked.\n5. **Three to five recordings**, chosen for what they show rather than recency: prefer a person's\n   second or third visit, where the repetition is visible.\n6. **Deploys touching that route**, if the codebase is connected.\n7. **Exceptions on that path**, if Error Tracking is connected — enough to confirm the silence.\n\n## Writing the report\n\nLead with the flow and who is stuck in it, not the page's exit rate. State what the person is\ntrying to do, what the app does instead, and why the app thinks it is right — a guard firing on\nincomplete state is correct behaviour, and the report reads as nonsense without that.\n\nSuggest a fix only when the evidence supports one. \"Step two returns a conflict because the\nworkspace it wants to create already exists on the account\" is a fix. \"Improve onboarding\" is not,\nand is worse than saying you don't know.\n",{"data":40,"body":48},{"name":4,"description":6,"compatibility":41,"allowed_tools":42,"metadata":45},"PostHog Signals agent (Claude sandbox). Read-only analytics + signal_scout_internal:write (scratchpad) + signal_scout_report:write (report channel), plus execute-sql over events and `$recording_observed`, read-data-schema, query-session-recordings-list, and the feature-gated vision-scanners-list \u002F vision-observations-list when available.\n",[43,44],"emit_report","edit_report",{"owner_team":46,"scope":47},"signals","session_replay",{"type":49,"children":50},"root",[51,59,65,84,96,103,117,171,184,190,365,371,382,387,420,425,432,455,461,466,472,477,558,564,569],{"type":52,"tag":53,"props":54,"children":55},"element","h1",{"id":4},[56],{"type":57,"value":58},"text","Signals scout: dead-end pages",{"type":52,"tag":60,"props":61,"children":62},"p",{},[63],{"type":57,"value":64},"You are a focused state-trap scout. Products gate access behind flows — onboarding, email\nverification, workspace setup — and a route guard sends anyone with incomplete state back to the\nstart of one. That guard is doing its job. Your job is the case where it has become a wall: the\nperson cannot complete the flow, so the guard fires again on every visit, and they never reach the\nproduct.",{"type":52,"tag":60,"props":66,"children":67},{},[68,74,76,82],{"type":52,"tag":69,"props":70,"children":71},"strong",{},[72],{"type":57,"value":73},"Incompletable-vs-merely-unfinished is the discriminator.",{"type":57,"value":75}," Someone who abandoned onboarding and\nhasn't come back is baseline — most people who start a flow don't finish it in one sitting. Signal\nis a person who ",{"type":52,"tag":77,"props":78,"children":79},"em",{},[80],{"type":57,"value":81},"returns",{"type":57,"value":83},", is redirected to the same step, and leaves again, repeatedly. Compare a\ngated page against its own history, never an absolute bar: a step that has always shed half its\narrivals is how that flow works.",{"type":52,"tag":60,"props":85,"children":86},{},[87,89,94],{"type":57,"value":88},"The mechanism worth naming, because it is the usual cause: a flow with side effects and no way to\nreconcile them. Step two creates something, step four marks the account complete, and the write\nthat marks completion never happens. On return, the guard sends the person back to step two, which\ntries to create what already exists and refuses. The refusal is a handled response — a validation\nmessage, not an exception — so ",{"type":52,"tag":69,"props":90,"children":91},{},[92],{"type":57,"value":93},"nothing throws, nothing alerts, and the funnel counts every\nattempt",{"type":57,"value":95},". The only trace is in the recordings.",{"type":52,"tag":97,"props":98,"children":100},"h2",{"id":99},"boundaries-read-before-authoring",[101],{"type":57,"value":102},"Boundaries — read before authoring",{"type":52,"tag":60,"props":104,"children":105},{},[106,108,115],{"type":57,"value":107},"Three sibling scouts own neighbouring surfaces. Check ",{"type":52,"tag":109,"props":110,"children":112},"code",{"className":111},[],[113],{"type":57,"value":114},"inbox-reports-list",{"type":57,"value":116}," before you author, and\ncite any overlapping report rather than restating it.",{"type":52,"tag":118,"props":119,"children":120},"ul",{},[121,136,157],{"type":52,"tag":122,"props":123,"children":124},"li",{},[125,134],{"type":52,"tag":69,"props":126,"children":127},{},[128],{"type":52,"tag":109,"props":129,"children":131},{"className":130},[],[132],{"type":57,"value":133},"signals-scout-session-replay",{"type":57,"value":135}," owns raw friction: rage-click and dead-click concentration on\na page or element, and recording capture integrity. If your finding is \"this element is\nfrustrating\", it is theirs. Yours is \"this person cannot get past this step, across visits\".",{"type":52,"tag":122,"props":137,"children":138},{},[139,148,150,155],{"type":52,"tag":69,"props":140,"children":141},{},[142],{"type":52,"tag":109,"props":143,"children":145},{"className":144},[],[146],{"type":57,"value":147},"signals-scout-replay-vision",{"type":57,"value":149}," owns scanner machinery and aggregate scanner drift — a\nmonitor's yes-rate creeping up, a scanner that stopped observing. You ",{"type":52,"tag":77,"props":151,"children":152},{},[153],{"type":57,"value":154},"read",{"type":57,"value":156}," scanner output as\nevidence; you do not report on the scanner itself.",{"type":52,"tag":122,"props":158,"children":159},{},[160,169],{"type":52,"tag":69,"props":161,"children":162},{},[163],{"type":52,"tag":109,"props":164,"children":166},{"className":165},[],[167],{"type":57,"value":168},"signals-scout-silent-failure",{"type":57,"value":170}," owns one named core action's completion rate, and looks for a\nswallowed exception behind a drop. Yours is defined by there being no exception to find, and\nstarts from the gated page rather than the flow.",{"type":52,"tag":60,"props":172,"children":173},{},[174,176,182],{"type":57,"value":175},"If a scanner on this surface has ",{"type":52,"tag":109,"props":177,"children":179},{"className":178},[],[180],{"type":57,"value":181},"emits_signals: true",{"type":57,"value":183},", it is already pushing one signal per\nsession into this same inbox. Never re-author what it pushed. Your finding must add what a\nper-session push structurally cannot: the same person, the same forced page, across days.",{"type":52,"tag":97,"props":185,"children":187},{"id":186},"sql-footguns",[188],{"type":57,"value":189},"SQL footguns",{"type":52,"tag":191,"props":192,"children":193},"ol",{},[194,220,262,293,333],{"type":52,"tag":122,"props":195,"children":196},{},[197,202,204,210,212,218],{"type":52,"tag":69,"props":198,"children":199},{},[200],{"type":57,"value":201},"Client clocks lie.",{"type":57,"value":203}," Sessions and events arrive dated into the future. Upper-bound every\nrecency window (",{"type":52,"tag":109,"props":205,"children":207},{"className":206},[],[208],{"type":57,"value":209},"AND timestamp \u003C= now() + INTERVAL 1 DAY",{"type":57,"value":211},") and never trust\n",{"type":52,"tag":109,"props":213,"children":215},{"className":214},[],[216],{"type":57,"value":217},"ORDER BY timestamp DESC LIMIT 1",{"type":57,"value":219}," to mean \"latest\" without it.",{"type":52,"tag":122,"props":221,"children":222},{},[223,252,254,260],{"type":52,"tag":69,"props":224,"children":225},{},[226,228,234,236,242,244,250],{"type":57,"value":227},"On ",{"type":52,"tag":109,"props":229,"children":231},{"className":230},[],[232],{"type":57,"value":233},"$recording_observed",{"type":57,"value":235},", count reach with ",{"type":52,"tag":109,"props":237,"children":239},{"className":238},[],[240],{"type":57,"value":241},"uniq(session_id)",{"type":57,"value":243},", never ",{"type":52,"tag":109,"props":245,"children":247},{"className":246},[],[248],{"type":57,"value":249},"uniq(person_id)",{"type":57,"value":251},".",{"type":57,"value":253}," The\nevent's ",{"type":52,"tag":109,"props":255,"children":257},{"className":256},[],[258],{"type":57,"value":259},"distinct_id",{"type":57,"value":261}," is a synthetic per-team scanner id for scheduled scans, not the end user.",{"type":52,"tag":122,"props":263,"children":264},{},[265,284,286,292],{"type":52,"tag":69,"props":266,"children":267},{},[268,270,276,277,283],{"type":57,"value":269},"Group scanners by ",{"type":52,"tag":109,"props":271,"children":273},{"className":272},[],[274],{"type":57,"value":275},"scanner_id",{"type":57,"value":243},{"type":52,"tag":109,"props":278,"children":280},{"className":279},[],[281],{"type":57,"value":282},"scanner_name",{"type":57,"value":251},{"type":57,"value":285}," The name is snapshotted per\nobservation, so a rename splits one scanner's history in two. Carry the name as a label via\n",{"type":52,"tag":109,"props":287,"children":289},{"className":288},[],[290],{"type":57,"value":291},"argMax(properties.scanner_name, timestamp)",{"type":57,"value":251},{"type":52,"tag":122,"props":294,"children":295},{},[296,307,309,315,317,323,325,331],{"type":52,"tag":69,"props":297,"children":298},{},[299,305],{"type":52,"tag":109,"props":300,"children":302},{"className":301},[],[303],{"type":57,"value":304},"scanner_output_tags",{"type":57,"value":306}," is a JSON-encoded array",{"type":57,"value":308},", not a native one. ",{"type":52,"tag":109,"props":310,"children":312},{"className":311},[],[313],{"type":57,"value":314},"JSONExtract(..., 'Array(String)')",{"type":57,"value":316},"\nbefore ",{"type":52,"tag":109,"props":318,"children":320},{"className":319},[],[321],{"type":57,"value":322},"arrayJoin",{"type":57,"value":324},", and union ",{"type":52,"tag":109,"props":326,"children":328},{"className":327},[],[329],{"type":57,"value":330},"scanner_output_tags_freeform",{"type":57,"value":332}," or you miss the freeform tags.",{"type":52,"tag":122,"props":334,"children":335},{},[336,347,349,355,357,363],{"type":52,"tag":69,"props":337,"children":338},{},[339,341,346],{"type":57,"value":340},"Only succeeded observations write ",{"type":52,"tag":109,"props":342,"children":344},{"className":343},[],[345],{"type":57,"value":233},{"type":57,"value":251},{"type":57,"value":348}," Zero events can mean \"no scanner\"\nor \"every observation failing\" — ",{"type":52,"tag":109,"props":350,"children":352},{"className":351},[],[353],{"type":57,"value":354},"vision-scanners-observations-list",{"type":57,"value":356}," with a ",{"type":52,"tag":109,"props":358,"children":360},{"className":359},[],[361],{"type":57,"value":362},"status",{"type":57,"value":364}," filter is\nthe only way to tell.",{"type":52,"tag":97,"props":366,"children":368},{"id":367},"the-discriminator",[369],{"type":57,"value":370},"The discriminator",{"type":52,"tag":60,"props":372,"children":373},{},[374,376,381],{"type":57,"value":375},"Emit a report when, for a gated page, ",{"type":52,"tag":69,"props":377,"children":378},{},[379],{"type":57,"value":380},"returning people are redirected to it and leave without\ncompleting, at a rate that has stepped away from that page's trailing two-week norm for the same\nday of week",{"type":57,"value":251},{"type":52,"tag":60,"props":383,"children":384},{},[385],{"type":57,"value":386},"Three things have to hold together:",{"type":52,"tag":191,"props":388,"children":389},{},[390,400,410],{"type":52,"tag":122,"props":391,"children":392},{},[393,398],{"type":52,"tag":69,"props":394,"children":395},{},[396],{"type":57,"value":397},"Repeat arrivals.",{"type":57,"value":399}," The same person reaching the page on separate sessions, ideally separate\ndays. One visit is someone who got distracted; four is a wall.",{"type":52,"tag":122,"props":401,"children":402},{},[403,408],{"type":52,"tag":69,"props":404,"children":405},{},[406],{"type":57,"value":407},"No completion event",{"type":57,"value":409}," between the first arrival and the last, on any of those visits.",{"type":52,"tag":122,"props":411,"children":412},{},[413,418],{"type":52,"tag":69,"props":414,"children":415},{},[416],{"type":57,"value":417},"No matching exception",{"type":57,"value":419},", where Error Tracking is connected. If something threw, the error\nsignals already have it — skip this check rather than blocking on it when Error Tracking isn't\nin play, because the recordings still say what happened.",{"type":52,"tag":60,"props":421,"children":422},{},[423],{"type":57,"value":424},"Where a Replay Vision dead-end monitor or session-outcome classifier is configured, lead the claim\nwith it — a verdict is a per-session judgment that the person was stuck, rather than an inference\nfrom where clicking stopped. Name the scanner so the reader can open the observations.",{"type":52,"tag":426,"props":427,"children":429},"h3",{"id":428},"write-nothing-when",[430],{"type":57,"value":431},"Write nothing when",{"type":52,"tag":118,"props":433,"children":434},{},[435,440,445,450],{"type":52,"tag":122,"props":436,"children":437},{},[438],{"type":57,"value":439},"The page is a natural terminus. Order confirmation, docs, a thank-you page — anywhere leaving is\nthe successful outcome. Learn these from the trailing norm, not a hardcoded list.",{"type":52,"tag":122,"props":441,"children":442},{},[443],{"type":57,"value":444},"Arrivals are first-time rather than returning. That is a flow with a drop-off, not a trap, and it\nbelongs to whoever owns that funnel.",{"type":52,"tag":122,"props":446,"children":447},{},[448],{"type":57,"value":449},"Traffic to the page changed enough to explain the rate on its own.",{"type":52,"tag":122,"props":451,"children":452},{},[453],{"type":57,"value":454},"Exceptions rose alongside it, per the third condition above.",{"type":52,"tag":426,"props":456,"children":458},{"id":457},"the-bar",[459],{"type":57,"value":460},"The bar",{"type":52,"tag":60,"props":462,"children":463},{},[464],{"type":57,"value":465},"A page needs enough sessions for the rate to mean anything. Skip anything under 50 sessions in the\nwindow, and raise that floor if you shorten the interval. Daily is the fleet default — traps build\nover days, and a shorter interval mostly adds noise.",{"type":52,"tag":97,"props":467,"children":469},{"id":468},"what-to-gather-before-writing",[470],{"type":57,"value":471},"What to gather before writing",{"type":52,"tag":60,"props":473,"children":474},{},[475],{"type":57,"value":476},"The report has to name what is blocking people, not just a page and a number.",{"type":52,"tag":191,"props":478,"children":479},{},[480,490,500,518,528,538,548],{"type":52,"tag":122,"props":481,"children":482},{},[483,488],{"type":52,"tag":69,"props":484,"children":485},{},[486],{"type":57,"value":487},"The rate and its norm",{"type":57,"value":489}," — what it was, what it is, over how many sessions.",{"type":52,"tag":122,"props":491,"children":492},{},[493,498],{"type":52,"tag":69,"props":494,"children":495},{},[496],{"type":57,"value":497},"The repeat shape",{"type":57,"value":499}," — how many distinct people, how many visits each, over how many days, and\nhow many have never once reached the product.",{"type":52,"tag":122,"props":501,"children":502},{},[503,508,510,516],{"type":52,"tag":69,"props":504,"children":505},{},[506],{"type":57,"value":507},"Replay Vision output",{"type":57,"value":509},", where a scanner exists: the dead-end monitor's verdict-yes count or\nthe classifier's ",{"type":52,"tag":109,"props":511,"children":513},{"className":512},[],[514],{"type":57,"value":515},"task_abandoned",{"type":57,"value":517}," share, cited by scanner name.",{"type":52,"tag":122,"props":519,"children":520},{},[521,526],{"type":52,"tag":69,"props":522,"children":523},{},[524],{"type":57,"value":525},"What they do before giving up",{"type":57,"value":527}," — this is the part only the recordings have, and it's what\nturns a rate into a cause. Look for: rage clicks on the control that should advance them, the\nsame field edited and resubmitted several times, attempts to navigate away that the guard\nbounces straight back, a reload, and dwell time that's long rather than short. Someone who\nleaves in four seconds bounced; someone who spent ninety seconds trying was blocked.",{"type":52,"tag":122,"props":529,"children":530},{},[531,536],{"type":52,"tag":69,"props":532,"children":533},{},[534],{"type":57,"value":535},"Three to five recordings",{"type":57,"value":537},", chosen for what they show rather than recency: prefer a person's\nsecond or third visit, where the repetition is visible.",{"type":52,"tag":122,"props":539,"children":540},{},[541,546],{"type":52,"tag":69,"props":542,"children":543},{},[544],{"type":57,"value":545},"Deploys touching that route",{"type":57,"value":547},", if the codebase is connected.",{"type":52,"tag":122,"props":549,"children":550},{},[551,556],{"type":52,"tag":69,"props":552,"children":553},{},[554],{"type":57,"value":555},"Exceptions on that path",{"type":57,"value":557},", if Error Tracking is connected — enough to confirm the silence.",{"type":52,"tag":97,"props":559,"children":561},{"id":560},"writing-the-report",[562],{"type":57,"value":563},"Writing the report",{"type":52,"tag":60,"props":565,"children":566},{},[567],{"type":57,"value":568},"Lead with the flow and who is stuck in it, not the page's exit rate. State what the person is\ntrying to do, what the app does instead, and why the app thinks it is right — a guard firing on\nincomplete state is correct behaviour, and the report reads as nonsense without that.",{"type":52,"tag":60,"props":570,"children":571},{},[572],{"type":57,"value":573},"Suggest a fix only when the evidence supports one. \"Step two returns a conflict because the\nworkspace it wants to create already exists on the account\" is a fix. \"Improve onboarding\" is not,\nand is worse than saying you don't know.",{"items":575,"total":637},[576,592,599,614,624],{"slug":577,"name":577,"fn":578,"description":579,"org":580,"tags":581,"stars":23,"repoUrl":24,"updatedAt":591},"signals-scout-ai-cost","monitor AI feature costs and performance","Watches cost per conversation for AI features and reports when it breaks from its recent norm while volume holds steady, attributing the change to a model, prompt, cache, or retry cause.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[582,585,588,589,590],{"name":583,"slug":584,"type":15},"Cost Optimization","cost-optimization",{"name":586,"slug":587,"type":15},"LLM","llm",{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-08-10T04:45:48.936016",{"slug":4,"name":4,"fn":5,"description":6,"org":593,"tags":594,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[595,596,597,598],{"name":21,"slug":22,"type":15},{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"slug":600,"name":600,"fn":601,"description":602,"org":603,"tags":604,"stars":23,"repoUrl":24,"updatedAt":613},"signals-scout-flag-debt","identify and remove stale feature flags","Finds feature flags whose decision is over but which are still evaluated in production – terminal rollouts left in place, or keys that no longer appear in any connected repo.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[605,608,609,610],{"name":606,"slug":607,"type":15},"Feature Flags","feature-flags",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},{"name":611,"slug":612,"type":15},"Tech Debt","tech-debt","2026-08-10T04:45:50.019808",{"slug":168,"name":168,"fn":615,"description":616,"org":617,"tags":618,"stars":23,"repoUrl":24,"updatedAt":623},"detect and diagnose silent application failures","Watches the completion rate of one named core action for breaks from its own norm, and reports the likely cause – with swallowed exceptions as the first thing it looks for.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[619,620,621,622],{"name":21,"slug":22,"type":15},{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-08-10T04:45:56.482808",{"slug":625,"name":625,"fn":626,"description":627,"org":628,"tags":629,"stars":23,"repoUrl":24,"updatedAt":636},"signals-scout-your-scout","configure PostHog signal scouts","What this scout watches and the condition under which it files a report.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[630,633,634,635],{"name":631,"slug":632,"type":15},"Automation","automation",{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-08-10T04:45:49.295902",5,{"items":639,"total":810},[640,655,665,677,690,703,719,732,746,760,778,795],{"slug":641,"name":641,"fn":642,"description":643,"org":644,"tags":645,"stars":652,"repoUrl":653,"updatedAt":654},"analyzing-expensive-users","analyze expensive users in AI observability","Analyze the most expensive users in AI observability and explain why they cost so much. Use when the user asks about top spenders, expensive users, per-user LLM cost, user-level cost drivers, or patterns behind high AI observability spend.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[646,649,650,651],{"name":647,"slug":648,"type":15},"Analytics","analytics",{"name":583,"slug":584,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},35568,"https:\u002F\u002Fgithub.com\u002FPostHog\u002Fposthog","2026-08-13T04:28:38.012786",{"slug":656,"name":656,"fn":657,"description":658,"org":659,"tags":660,"stars":652,"repoUrl":653,"updatedAt":664},"analyzing-task-runs","analyze PostHog task run efficiency","Analyze a completed PostHog task run for inefficiencies — environment failures, missing CLI tools, verbose commands, redundant work, wasted retries — and file evidence-backed findings through the report_insight tool. Use when a task asks to analyze a run, produce run insights or a task analysis, or review a run's efficiency from an attached run log. Covers the log query protocol (bounded jq queries over the raw JSONL), both log schemas, the finding taxonomy, and evidence verification.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[661,662,663],{"name":21,"slug":22,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-08-26T03:35:51.541494",{"slug":666,"name":666,"fn":667,"description":668,"org":669,"tags":670,"stars":652,"repoUrl":653,"updatedAt":676},"auditing-endpoints","audit PostHog project endpoints","Audit every endpoint in a PostHog project for staleness, failed materialisations, and unused materialised versions. Use when the user asks \"what endpoints can I clean up?\", \"are any of my endpoints broken?\", \"which materialised versions are still being called?\", or wants a one-shot cleanup pass over the Endpoints product. Produces a prioritised report grouped by issue type, with recommended actions but does not modify anything without explicit confirmation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[671,672,675],{"name":647,"slug":648,"type":15},{"name":673,"slug":674,"type":15},"Audit","audit",{"name":9,"slug":8,"type":15},"2026-06-08T08:08:33.693989",{"slug":678,"name":678,"fn":679,"description":680,"org":681,"tags":682,"stars":652,"repoUrl":653,"updatedAt":689},"auditing-warehouse-source-health","audit PostHog data warehouse source health","Audit the health of a PostHog project's data warehouse sources and syncs — find every broken or degraded source connection, sync schema, and webhook channel. Use when the user asks \"why are my imports failing?\", \"what's broken with my sources?\", \"why is my warehouse data stale?\", or wants a one-shot triage of source\u002Fsync health before deciding where to dig in. Produces a prioritized report grouped by severity, with recommended next steps. For materialized-view health use `auditing-warehouse-view-health`; for a single failing sync use `diagnosing-failed-warehouse-syncs`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[683,684,687,688],{"name":673,"slug":674,"type":15},{"name":685,"slug":686,"type":15},"Data Warehouse","data-warehouse",{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-06-18T08:22:57.67984",{"slug":691,"name":691,"fn":692,"description":693,"org":694,"tags":695,"stars":652,"repoUrl":653,"updatedAt":702},"auditing-warehouse-view-health","audit PostHog materialized view health","Audit the health of a PostHog project's materialized views (saved queries) — find every failed materialization and flag unused or stale materialized views that cost storage and compute. Use when the user asks \"which of my views are broken?\", \"why is this materialized view failing?\", \"are any of my views wasting compute?\", or wants a one-shot triage of view health. For source\u002Fsync health use `auditing-warehouse-source-health`.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[696,697,698,701],{"name":673,"slug":674,"type":15},{"name":685,"slug":686,"type":15},{"name":699,"slug":700,"type":15},"Performance","performance",{"name":9,"slug":8,"type":15},"2026-06-18T08:25:10.936787",{"slug":704,"name":704,"fn":705,"description":706,"org":707,"tags":708,"stars":652,"repoUrl":653,"updatedAt":718},"authoring-data-quality-checks","author data quality checks for warehouse tables","Adds and runs data quality checks (dbt-test style assertions) on a project's warehouse tables and saved-query views: not-null, uniqueness, accepted values, referential integrity, row-count bounds, freshness, and custom HogQL. Use when asked to test a model, validate a view, check for nulls or duplicates, add data quality checks, find out why a number looks wrong, or judge whether a warehouse table is trustworthy before using it in an analysis. To describe what data *means* (metrics, certifications, joins), see setting-up-data-catalog instead. Trigger terms: data quality, data test, dbt test, not null check, uniqueness check, freshness check, referential integrity, row count check, validate model, is this table trustworthy.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[709,710,713,716],{"name":647,"slug":648,"type":15},{"name":711,"slug":712,"type":15},"Data Engineering","data-engineering",{"name":714,"slug":715,"type":15},"Data Quality","data-quality",{"name":717,"slug":717,"type":15},"dbt","2026-08-19T03:59:25.329274",{"slug":720,"name":720,"fn":721,"description":722,"org":723,"tags":724,"stars":652,"repoUrl":653,"updatedAt":731},"authoring-error-tracking-alerts","author PostHog error tracking alerts","Author error tracking alerts that fire when an issue is created, reopened, or starts spiking. Use when the user asks to set up error notifications, route exceptions to Slack\u002Fwebhook\u002FLinear, or evaluate which error events are worth alerting on. Covers trigger-event selection, integration choice, dedup against existing alerts, and shipping with the canonical message body shape.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[725,728,729,730],{"name":726,"slug":727,"type":15},"Alerting","alerting",{"name":21,"slug":22,"type":15},{"name":13,"slug":14,"type":15},{"name":9,"slug":8,"type":15},"2026-08-13T04:28:36.025103",{"slug":733,"name":733,"fn":734,"description":735,"org":736,"tags":737,"stars":652,"repoUrl":653,"updatedAt":745},"authoring-log-alerts","author log alerts in PostHog","Author useful, low-noise log alerts on services in a PostHog project. Use when the user asks to set up alerts for their logs, suggest alerts they should add, or evaluate whether a service is worth monitoring. Covers service triage, baseline characterisation, threshold drafting, back-testing via simulate, and shipping with a notification destination.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[738,739,740,741,744],{"name":647,"slug":648,"type":15},{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"name":742,"slug":743,"type":15},"Operations","operations",{"name":9,"slug":8,"type":15},"2026-08-13T04:28:20.051489",{"slug":747,"name":747,"fn":748,"description":749,"org":750,"tags":751,"stars":652,"repoUrl":653,"updatedAt":759},"building-canvases","create and edit PostHog canvases","Create or edit a PostHog freeform canvas — a sandboxed browser application (data board, document, form, small tool, graphics experiment) stored in PostHog and rendered by the desktop\u002Fweb app. Use when a task asks to build, generate, update, or fix a standalone canvas app, or when a freeform canvas id is given as the publish target. For grid\u002Fhome canvases, widget placements, or reusable components, use composing-grid-canvases instead. Covers resolving or creating the target canvas, choosing an implementation approach (React + Quill vs plain HTML\u002Fbrowser APIs), the read → edit → validate → publish → build loop, and which companion canvas skills to load for the details.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[752,753,755,756],{"name":631,"slug":632,"type":15},{"name":754,"slug":29,"type":15},"Design",{"name":9,"slug":8,"type":15},{"name":757,"slug":758,"type":15},"Prototyping","prototyping","2026-08-26T03:35:54.632968",{"slug":761,"name":761,"fn":762,"description":763,"org":764,"tags":765,"stars":652,"repoUrl":653,"updatedAt":777},"building-html-canvases","author HTML and CSS PostHog canvases","Author a PostHog canvas with semantic HTML, CSS, and direct browser APIs — documents, articles, generative graphics, 2D canvas and WebGL experiences, and focused experiments where React components add no useful structure. Use after building-canvases has routed a canvas request to a plain-HTML\u002Fbrowser-API implementation. Covers the thin component wrapper the current runtime requires, styling and theming without Quill, drawing surfaces, and animation\u002Fcleanup patterns.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[766,769,770,773,776],{"name":767,"slug":768,"type":15},"CSS","css",{"name":754,"slug":29,"type":15},{"name":771,"slug":772,"type":15},"Graphics","graphics",{"name":774,"slug":775,"type":15},"HTML","html",{"name":9,"slug":8,"type":15},"2026-08-22T03:23:06.404123",{"slug":779,"name":779,"fn":780,"description":781,"org":782,"tags":783,"stars":652,"repoUrl":653,"updatedAt":794},"building-react-quill-canvases","build React and Quill canvases","Author the React + Quill implementation of a PostHog canvas: the single-component contract, the allowed imports, Quill (PostHog's design system) component and composition rules, theme-aware design tokens, loading skeletons, and the in-canvas date picker. Use after building-canvases has routed a canvas request to a React implementation — dashboards, data boards, forms, tools, or any canvas that should look native to PostHog.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[784,785,788,791],{"name":754,"slug":29,"type":15},{"name":786,"slug":787,"type":15},"Frontend","frontend",{"name":789,"slug":790,"type":15},"React","react",{"name":792,"slug":793,"type":15},"UI Components","ui-components","2026-08-26T03:35:53.599633",{"slug":796,"name":796,"fn":797,"description":798,"org":799,"tags":800,"stars":652,"repoUrl":653,"updatedAt":809},"building-workflows","build and edit PostHog workflows","Build, edit, test, enable, and monitor PostHog workflows over MCP. Author the action\u002Fedge graph so it runs and opens cleanly in the visual editor, then change drafts surgically with patch operations. Use when asked to build, set up, automate, change, fix, or debug a workflow, campaign, broadcast, drip sequence, or event-triggered automation in the workflows product.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[801,802,805,806],{"name":631,"slug":632,"type":15},{"name":803,"slug":804,"type":15},"MCP","mcp",{"name":9,"slug":8,"type":15},{"name":807,"slug":808,"type":15},"Workflow Automation","workflow-automation","2026-08-10T04:16:26.294119",257]