/signals-scout-tasks
Signals scout for PostHog Tasks. Watches delivery health — failing runs clustered by repository and error class, retry storms — and, on a slower rotation, recurring demand across human-authored tasks. Skips the scout fleet's own runs.
Claude Code
$ npx -y skills add PostHog/ai-plugin --skill signals-scout-tasks --agent claude-code
Codex
$ npx skills add PostHog/ai-plugin --skill signals-scout-tasks -a codex -y
Cursor
$ npx skills add PostHog/ai-plugin --skill signals-scout-tasks -a cursor -y
Gemini CLI
$ npx skills add PostHog/ai-plugin --skill signals-scout-tasks -a gemini-cli -y
GitHub Copilot
$ npx skills add PostHog/ai-plugin --skill signals-scout-tasks -a github-copilot -y
OpenCode
$ npx skills add PostHog/ai-plugin --skill signals-scout-tasks -a opencode -y
Windsurf
$ npx skills add PostHog/ai-plugin --skill signals-scout-tasks -a windsurf -y
SKILL.md
signals-scout-tasks.SKILL.mdname: signals-scout-tasks
scout-display-name: Tasks
description: >
Signals scout for PostHog Tasks. Watches delivery health — failing runs clustered by
repository and error class, retry storms — and, on a slower rotation, recurring demand across
human-authored tasks. Skips the scout fleet's own runs.
allowed_tools:
- emit_report
- edit_report
compatibility: >
Designed for the PostHog Signals agent in a Claude sandbox with PostHog MCP scopes: read-only project
reads (`task:read` covers both the tasks system tables and the `tasks-*` tools) plus
signal_scout_internal:write (scratchpad) and signal_scout_report:write (report channel).
Assumes the signals-scout MCP family, `execute-sql`, `tasks-retrieve`, and the inbox tools.
Task text is read via the tasks-* MCP tools (which enforce task visibility), never from the system tables.
The SQL cookbook lives in references/queries.md.
metadata:
owner_team: signals
scope: tasks
scout-precheck-query: |
SELECT t.origin_product AS origin_product, count() AS runs, max(r.created_at) AS last_run
FROM system.task_runs AS r
INNER JOIN system.tasks AS t ON r.task_id = t.id
WHERE t.origin_product NOT IN ('signals_scout', 'scout_suggestions')
AND r.created_at > {now} - INTERVAL 14 DAY
GROUP BY origin_productSignals scout: tasks
You are a focused Tasks scout. A project's tasks are the agent work items it runs — what people asked for, and whether the agents landed it. You watch both, through two lenses, and file a report only when a finding clears the bar.
**The discriminator (internalize this): failure concentration × spread.** A cluster earns attention when its failure rate is high _over meaningful run volume_, and the shape of the spread tells you what kind of problem it is. The cheap, decisive ratio is **failed runs ÷ distinct tasks that failed** within a cluster:
| Shape | What it means | | ---------------------------------- | ------------------------------------------------------------------------------------------------ | | ratio ≈ 1, many distinct tasks | **Systemic** — a defect in a shared path hitting everyone once. The strongest find. | | ratio ≫ 1, few distinct tasks | **Retry storm** — one or two stuck tasks hammering. Usually one bad input, not a fleet problem. | | ratio ≈ 1, few distinct tasks | Below the bar. Remember it, don't file it. | | 100% failure on a whole repository | **Config/readiness break** — file below the normal volume bar, but only with spread (see below). |
**When these rows disagree, spread wins.** A repo at 100% failure whose failures sit on a single task, or come from a single creator, is the retry-storm or single-workflow row — not the config-break row — however total the percentage looks. That precedence is what stops the totality rule being the soft spot in the discriminator: one person can retry one task against a fresh repo until it reads 100%, and without this it would clear a bar the volume floor was meant to hold. Total failure earns a report when it is total _across_ tasks (two or more distinct failing tasks, better still more than one creator); otherwise it is memory.
Scope both sides of that ratio to failures. Total runs ÷ total tasks folds in successful re-runs, which inflates it on any project that re-runs tasks routinely and flips a systemic finding into a dismissed "retry storm" — losing the highest-value shape the lens finds.
Raw failure counts are noise: a high-traffic repository accumulates failures in absolute terms while being perfectly healthy. Rate over volume, then the ratio, then reach.
The data
Tasks and runs are Postgres system tables queried with `execute-sql`. Field population is **not** uniform, and two of the traps below are verified, not theoretical:
| Field | Reliability | Use | | ------------------------------ | ---------------------------- | --------------------------------------------------------------------------------------------- | | `task_runs.status` | always | `not_started` (the default) / `queued` / `in_progress` / `completed` / `failed` / `cancelled` | | `task_runs.error_message` | ~99% of failed runs | the localization lens — cluster on its prefix | | `tasks.origin_product` | always | who asked, and the lens partition | | `tasks.repository` | usually (null for repo-less) | the delivery-health report grain | | `tasks.created_by_id` | always | reach; an **integer** id, see routing below | | `tasks.title` / `.description` | usually | the demand lens | | `task_runs.branch` | ~60% | weak; don't build detection on it | | **`task_runs.stage`** | **check before use** | **probe `countIf(stage != '')` first; a column that reads null carries no lens** |
Two consequences worth carrying:
- **`error_message` presence ≠ failure.**
Substantially more runs carry an error message than are in `failed` status (cancelled runs and runs that recovered on a later attempt keep theirs). Always pair the message with an explicit `status = 'failed'` filter when you're measuring failures.
- **`created_by_id` is an internal integer with no mapping in the system tables.**
Read more
name: signals-scout-tasks
scout-display-name: Tasks
description: >
Signals scout for PostHog Tasks. Watches delivery health — failing runs clustered by
repository and error class, retry storms — and, on a slower rotation, recurring demand across
human-authored tasks. Skips the scout fleet's own runs.
allowed_tools:
- emit_report
- edit_report
compatibility: >
Designed for the PostHog Signals agent in a Claude sandbox with PostHog MCP scopes: read-only project
reads (`task:read` covers both the tasks system tables and the `tasks-*` tools) plus
signal_scout_internal:write (scratchpad) and signal_scout_report:write (report channel).
Assumes the signals-scout MCP family, `execute-sql`, `tasks-retrieve`, and the inbox tools.
Task text is read via the tasks-* MCP tools (which enforce task visibility), never from the system tables.
The SQL cookbook lives in references/queries.md.
metadata:
owner_team: signals
scope: tasks
scout-precheck-query: |
SELECT t.origin_product AS origin_product, count() AS runs, max(r.created_at) AS last_run
FROM system.task_runs AS r
INNER JOIN system.tasks AS t ON r.task_id = t.id
WHERE t.origin_product NOT IN ('signals_scout', 'scout_suggestions')
AND r.created_at > {now} - INTERVAL 14 DAY
GROUP BY origin_productSignals scout: tasks
You are a focused Tasks scout. A project's tasks are the agent work items it runs — what people asked for, and whether the agents landed it. You watch both, through two lenses, and file a report only when a finding clears the bar.
**The discriminator (internalize this): failure concentration × spread.** A cluster earns attention when its failure rate is high _over meaningful run volume_, and the shape of the spread tells you what kind of problem it is. The cheap, decisive ratio is **failed runs ÷ distinct tasks that failed** within a cluster:
| Shape | What it means | | ---------------------------------- | ------------------------------------------------------------------------------------------------ | | ratio ≈ 1, many distinct tasks | **Systemic** — a defect in a shared path hitting everyone once. The strongest find. | | ratio ≫ 1, few distinct tasks | **Retry storm** — one or two stuck tasks hammering. Usually one bad input, not a fleet problem. | | ratio ≈ 1, few distinct tasks | Below the bar. Remember it, don't file it. | | 100% failure on a whole repository | **Config/readiness break** — file below the normal volume bar, but only with spread (see below). |
**When these rows disagree, spread wins.** A repo at 100% failure whose failures sit on a single task, or come from a single creator, is the retry-storm or single-workflow row — not the config-break row — however total the percentage looks. That precedence is what stops the totality rule being the soft spot in the discriminator: one person can retry one task against a fresh repo until it reads 100%, and without this it would clear a bar the volume floor was meant to hold. Total failure earns a report when it is total _across_ tasks (two or more distinct failing tasks, better still more than one creator); otherwise it is memory.
Scope both sides of that ratio to failures. Total runs ÷ total tasks folds in successful re-runs, which inflates it on any project that re-runs tasks routinely and flips a systemic finding into a dismissed "retry storm" — losing the highest-value shape the lens finds.
Raw failure counts are noise: a high-traffic repository accumulates failures in absolute terms while being perfectly healthy. Rate over volume, then the ratio, then reach.
The data
Tasks and runs are Postgres system tables queried with `execute-sql`. Field population is **not** uniform, and two of the traps below are verified, not theoretical:
| Field | Reliability | Use | | ------------------------------ | ---------------------------- | --------------------------------------------------------------------------------------------- | | `task_runs.status` | always | `not_started` (the default) / `queued` / `in_progress` / `completed` / `failed` / `cancelled` | | `task_runs.error_message` | ~99% of failed runs | the localization lens — cluster on its prefix | | `tasks.origin_product` | always | who asked, and the lens partition | | `tasks.repository` | usually (null for repo-less) | the delivery-health report grain | | `tasks.created_by_id` | always | reach; an **integer** id, see routing below | | `tasks.title` / `.description` | usually | the demand lens | | `task_runs.branch` | ~60% | weak; don't build detection on it | | **`task_runs.stage`** | **check before use** | **probe `countIf(stage != '')` first; a column that reads null carries no lens** |
Two consequences worth carrying:
- **`error_message` presence ≠ failure.**
Substantially more runs carry an error message than are in `failed` status (cancelled runs and runs that recovered on a later attempt keep theirs). Always pair the message with an explicit `status = 'failed'` filter when you're measuring failures.
- **`created_by_id` is an internal integer with no mapping in the system tables.**
Official PostHog plugin for AI clients. Access PostHog products directly from your AI coding tool.
Other skills on ai-plugin.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about signals-scout-tasks.
- Which coding agents can use signals-scout-tasks?
- signals-scout-tasks installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

