Skip to content

Commit 13dd2e2

Browse files
chore: sync skills (agent-skills-v0.706.0, context-mill@v1.41.0) (#176)
Co-authored-by: releaser-ai-plugin[bot] <273148615+releaser-ai-plugin[bot]@users.noreply.github.com>
1 parent 257a7d5 commit 13dd2e2

109 files changed

Lines changed: 996 additions & 586 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "posthog",
33
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from your AI coding tool. Optionally capture Claude Code sessions to PostHog LLM Analytics.",
4-
"version": "1.1.55",
4+
"version": "1.1.56",
55
"author": {
66
"name": "PostHog",
77
"email": "hey@posthog.com",

.codex-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "posthog",
3-
"version": "1.0.53",
3+
"version": "1.0.54",
44
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Codex",
55
"author": {
66
"name": "PostHog",

.cursor-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "posthog",
33
"displayName": "PostHog",
4-
"version": "1.1.49",
4+
"version": "1.1.50",
55
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Cursor",
66
"author": {
77
"name": "PostHog",

gemini-extension.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "posthog",
3-
"version": "1.0.51",
3+
"version": "1.0.52",
44
"description": "Access PostHog analytics, feature flags, experiments, error tracking, and insights directly from Gemini CLI",
55
"mcpServers": {
66
"posthog": {

skills/.sync-manifest

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ managing-endpoint-versions
7676
managing-experiment-lifecycle
7777
managing-path-cleaning-rules
7878
managing-reminders
79+
managing-streamlit-apps
7980
managing-subscriptions
8081
planning-voice-agent-user-interviews
8182
querying-posthog-data
@@ -105,7 +106,6 @@ signals-scout-feature-flags
105106
signals-scout-general
106107
signals-scout-health-checks
107108
signals-scout-inbox-validation
108-
signals-scout-ingestion-warnings
109109
signals-scout-insight-alerts
110110
signals-scout-logs
111111
signals-scout-mcp-tool-calls
@@ -128,3 +128,4 @@ triaging-visual-review-runs
128128
tuning-incremental-sync-config
129129
turning-engineering-analytics-into-insights
130130
working-with-skills
131+
writing-streamlit-apps

skills/analyzing-expensive-users/SKILL.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ Use this first when the question asks for the most expensive users:
6060
```sql
6161
posthog:execute-sql
6262
SELECT
63-
argMax(user_tuple, timestamp) AS __llm_person,
6463
distinct_id,
64+
argMax(email, timestamp) AS email,
65+
argMax(name, timestamp) AS name,
6566
countDistinctIf(ai_trace_id, notEmpty(ai_trace_id)) AS traces,
6667
count() AS generations,
6768
countIf(notEmpty(ai_error) OR ai_is_error = 'true') AS errors,
@@ -81,7 +82,8 @@ FROM (
8182
toString(properties.$ai_is_error) AS ai_is_error,
8283
toInt(properties.$ai_input_tokens) AS ai_input_tokens,
8384
toInt(properties.$ai_output_tokens) AS ai_output_tokens,
84-
tuple(distinct_id, person.created_at, person.properties) AS user_tuple
85+
toString(person.properties.email) AS email,
86+
toString(person.properties.name) AS name
8587
FROM events
8688
WHERE event = '$ai_generation'
8789
AND timestamp >= now() - INTERVAL 30 DAY
@@ -101,8 +103,10 @@ AND (
101103
)
102104
```
103105

104-
Use person properties only for labeling, such as email or name. Do not expose
105-
more personal data than needed.
106+
Project only the explicit label columns you need, such as `email` and `name`.
107+
Never select the raw `person.properties` object or a tuple containing it: it
108+
serializes the full property blob into the result and leaks personal data far
109+
beyond a label. If a user has no email or name, fall back to `distinct_id`.
106110

107111
### 2. Establish the baseline
108112

@@ -312,7 +316,9 @@ the trace timestamp so the UI opens the right time window.
312316
Lead with the answer, not the queries. A good response has:
313317

314318
1. **Top users** - ranked by total cost, with total cost, share of spend,
315-
generations, traces, average cost per generation, and error rate.
319+
generations, traces, average cost per generation, and error rate. Identify
320+
each user by a label only (email, name, or `distinct_id`). Do not print raw
321+
`person.properties` objects or other personal fields the user did not ask for.
316322
2. **Why they are expensive** - one or two concrete drivers per user, compared
317323
against the baseline.
318324
3. **Evidence** - model/token/cache/custom-dimension breakdowns plus linked

skills/authoring-scouts/SKILL.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ For an **existing scout**, tune with `posthog:scout-config-update` (find the `id
112112
The standard flow is to make a scout and let it write — seeing what actually lands is the fastest way to calibrate it.
113113
Set **`emit=false` (dry-run)** only when you want to be extra careful: the scout still runs and logs its reasoning but writes nothing to the inbox.
114114
Reach for dry-run on a scout you expect to be chatty, expensive, or high-stakes; for most scouts, just writing and watching the inbox is the better loop.
115+
- `auto_pause_exempt` — defaults to `false`.
116+
A scout whose reports nobody acts on is warned and then paused automatically (`pause_reason=ignored`) — every run costs a sandbox agent, so a scout producing output no human consumes shouldn't keep running forever. A scout that is merely quiet is only flagged (`pause_reason=no_output`, a warning that never advances to a pause), since a watch scout's silence can be its job.
117+
`-config-list` shows the warning as `status=pending_pause` and the pause as `status=paused_by_system`; setting `enabled=true` again resumes the scout, and marks it exempt so the sweep never overrules a person twice.
118+
Set `auto_pause_exempt=true` up front for a watchdog scout whose whole job is to stay quiet, so it never even picks up the quiet flag.
115119

116120
## Steering with notes (no authoring needed)
117121

skills/authoring-scouts/references/lifecycle-and-testing.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ How scouts get discovered, scheduled, and dispatched; the two distribution paths
2121
The body is the system prompt; the agent orients, explores, files reports or remembers, and writes a one-paragraph summary to the run row.
2222

2323
Pausing a scout = `enabled=false`.
24+
That records `status=paused_by_user`, which automatic lifecycle sweeps never resume or re-pause; `enabled=true` resumes from any pause, including a system-applied one (`status=paused_by_system`, cause in the read-only `pause_reason`).
25+
Config responses expose `status` and `pause_reason` read-only; writes flow through `enabled`.
2426
Slowing it = a larger `run_interval_minutes`.
2527
Dry-running it = `emit=false`.
2628
All three via `posthog:scout-config-update` (get the `id` from `-config-list`), or set at creation time in the nested `config` object passed to `posthog:scout-create-prepare`.

skills/authoring-scouts/references/report-contract.md

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Judges the report for safety, then persists it at the judged status.
3636
| `actionability_explanation` | string | One sentence justifying the actionability call below. |
3737
| `actionability` | enum | `immediately_actionable` / `requires_human_input` / `not_actionable`. You make this call — the channel does not re-research it. |
3838
| `already_addressed` | bool, default `false` | Set when the underlying issue is already handled and you're filing for the record. |
39+
| `charts` | list, ≤20, optional | Queries the inbox draws on the report — the report's full set, replacing any it already had. Each `{chart_id, title, query, caption?, size?}`. See _Attaching charts_ below. |
3940

4041
**Status is decided for you, from safety × actionability:**
4142

@@ -48,6 +49,83 @@ Judges the report for safety, then persists it at the judged status.
4849

4950
The result tells you what happened: `report_id` (always set when a report was persisted — **even when suppressed**, so you can edit or dedup against it), `report_status` (the birth status — `ready` / `pending_input` / `suppressed` — the field is named `report_status` in the response, not `status`), `emitted` (true only when it actually surfaced — `READY` / `PENDING_INPUT`), `safety_explanation`, and `skipped_reason` (set only when a preflight gate stopped the call before any report was created — the AI-data-processing / source-enabled gates that govern every scout write).
5051

52+
### Attaching charts
53+
54+
`charts` puts the data next to the claim, so a reader sees the move instead of taking the number on trust.
55+
Worth it when the _shape_ is the point — a trend that broke, a distribution that shifted, a funnel step that collapsed.
56+
A chart restating one number the summary already gives is noise; just write the number.
57+
58+
| Field | Type | Notes |
59+
| ---------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
60+
| `chart_id` | string, required | Your own slug (lowercase letters, numbers, `_`, `-`). How the summary points at the chart, and the key a later edit refreshes it under. Unique within the report. |
61+
| `title` | string, required | Heading above the chart. |
62+
| `query` | object, required | An `InsightVizNode`, `DataVisualizationNode` (a `HogQLQuery` source, plus `display` and `chartSettings` for a graph), or `SavedInsightNode` (by `shortId`). Any other `kind` is refused at write time. |
63+
| `caption` | string, optional | One line on what to look at. |
64+
| `size` | enum, optional | `small` / `medium` / `large`. Leave it out unless the default looks wrong — the inbox sizes a chart from its query (a big single number gets a short box, a retention grid a tall scrolling one). |
65+
66+
A trends chart and a graph built from SQL, as they arrive in `charts`:
67+
68+
```json
69+
[
70+
{
71+
"chart_id": "exceptions-daily",
72+
"title": "Exceptions per day",
73+
"caption": "The step up starts on 18 June.",
74+
"query": {
75+
"kind": "InsightVizNode",
76+
"source": {
77+
"kind": "TrendsQuery",
78+
"dateRange": { "date_from": "2026-06-01", "date_to": "2026-07-02" },
79+
"interval": "day",
80+
"series": [{ "kind": "EventsNode", "event": "$exception", "math": "total" }],
81+
"trendsFilter": { "display": "ActionsLineGraph" }
82+
}
83+
}
84+
},
85+
{
86+
"chart_id": "exceptions-by-type",
87+
"title": "People affected, by exception type",
88+
"query": {
89+
"kind": "DataVisualizationNode",
90+
"source": {
91+
"kind": "HogQLQuery",
92+
"query": "SELECT exception_type, uniq(distinct_id) AS people FROM ... GROUP BY exception_type ORDER BY people DESC"
93+
},
94+
"display": "ActionsBar",
95+
"chartSettings": { "xAxis": { "column": "exception_type" }, "yAxis": [{ "column": "people" }] }
96+
}
97+
}
98+
]
99+
```
100+
101+
**A graph from SQL needs its axes named.** Setting `display` without `chartSettings` draws an empty box; `chartSettings.xAxis.column` and `chartSettings.yAxis[].column` say which columns of the result are which.
102+
Omit `display` altogether and the node renders the result table, which reads better than a chart for a handful of rows.
103+
104+
**Only the node's `kind` and its serialized size are checked on write.** A well-formed node of an allowed kind carrying a broken query is stored without complaint, then fails to draw when a reader opens the report, and nothing reports that back to the scout.
105+
So a scout should attach a query it has already run in the same session, or point at an insight that already exists via `SavedInsightNode`, rather than composing a node from memory.
106+
This is the single most useful thing to reinforce in a scout body that leans on charts.
107+
108+
**A chart query must not carry anything executable.** HogVM `bytecode` (what conditional formatting compiles to), a nested `HogQuery`, and `sendRawQuery` are each refused with a 400 wherever they sit in the node, because a chart renders data rather than running code in the reader's session.
109+
A nested `SuggestedQuestionsQuery` is refused the same way, for cost rather than execution: its runner calls an LLM, so a chart carrying one buys a completion every time a reader opens the report.
110+
A query over a warehouse connection is fine as long as it goes through HogQL: keep `connectionId`, drop `sendRawQuery`.
111+
So a direct-warehouse query you ran with the raw-SQL bypass has to be rewritten before it can be attached.
112+
113+
**Placement comes from the summary.** A markdown link with a `chart:` target — `[Daily signups](chart:signups-drop)` — draws the chart at that point in the body; a chart you never reference still renders, after the prose.
114+
Reference each chart once: a repeated reference reads as pointing back at the chart, not as asking for a second copy of it.
115+
Two references in one paragraph sit side by side, so put a pair you want compared in a paragraph of their own.
116+
A reference inside a code span, a table cell, or a heading has no room to draw — its chart falls to the end of the report instead.
117+
118+
**The summary has to read without the charts.** A report can also be delivered to Slack, where nothing draws and each reference degrades to the plain label it was given.
119+
"Signups fell 60% over the week" survives that; "the chart below shows the drop" leaves a Slack reader with nothing.
120+
121+
**Pin the window** to absolute dates wherever the node supports it, so a reader opening the report days later sees the data you wrote about rather than whatever a relative range resolves to then.
122+
123+
**`charts` on an edit is the report's whole set, not an addition.**
124+
It replaces what the report had, the way `summary` replaces the summary — so send every chart you want kept, and re-send an id under a newer window to refresh that chart.
125+
Leave `charts` out entirely and the report keeps the ones it has; read the report first (`inbox-reports-retrieve` returns its `charts`) when you mean to add to them.
126+
Send `charts: []` to take every chart down, for when the finding has moved on and the old chart would now mislead.
127+
Cap is **20 charts per report** (and a combined query-size budget), which is far more than most reports should use. Each chart runs its query when the report is opened, so attach the ones that carry the argument rather than everything you looked at: three charts a reader studies beat a dozen they scroll past.
128+
51129
### Opening a draft PR (autostart)
52130

53131
A surfaced, immediately-actionable report can open a draft PR automatically — the same autostart path the pipeline uses.
@@ -105,7 +183,7 @@ The fleet's reviewer map should compound over time.
105183
## `edit_report` — update an existing report
106184

107185
Rewrite `title`/`summary`, append a note, and/or set `suggested_reviewers` on a report that already exists.
108-
Pass `run_id` (the current run) and `report_id`, plus at least one of `title`, `summary`, `append_note`, `suggested_reviewers`.
186+
Pass `run_id` (the current run) and `report_id`, plus at least one of `title`, `summary`, `append_note`, `suggested_reviewers`, `charts`.
109187

110188
`edit_report` can target **any** of the team's inbox reports — not just ones a scout authored.
111189
That makes it the right tool when a later run learns something about a report the pipeline (or another scout) created.

0 commit comments

Comments
 (0)