voc-extract
When to use
- A backlog or planning round needs grounded user-voice signal, not anecdotes.
- A round of bug reports / feature requests / Sentry events has accumulated and the team needs themes with citation per theme.
- A roadmap proposal needs a "what users keep telling us" backing section.
Do NOT use this skill for live interviews
(discovery-interview) or for
quantitative funnel diagnosis (funnel-analysis).
Bounded scope
- Read-only on artefacts the host already has — local repo issues
(
gh issue list), PR discussions (gh pr view), Sentry projects
the team owns. No external scrape, no SaaS API calls.
- Chat-export sourcing (Discord, Slack) is deferred pending
privacy review (council Q5, SHIP-WITHOUT). If a request asks for
chat-derived VoC, refuse and route the user to a privacy review.
- No PII surfacing — quotes are paraphrased to remove names,
emails, tenant identifiers; verbatim is reserved for product-team
artefacts inside the repo.
Cognition cluster
- Mental model 15 — Signal vs noise. A loud single reporter
swamps quiet recurring patterns; rank by distinct authors, not
comment count. See
docs/contracts/mental-models.md § 15.
- Mental model 14 — Pareto. Roughly 20% of themes carry 80% of
the contact volume; cut the long tail explicitly so the team acts
on the head. See
mental-models.md § 14.
- Mental model 22 — Data-informed, not data-driven. Issue counts
are evidence, not voting; weight by recency, severity, and segment
before recommending. See
mental-models.md § 22.
- Product context-spine slot. Read product for segments,
non-goals, and focal jobs; do not surface themes that fall outside
the declared scope without a scope-violation flag. See
context-spine.
Procedure
1. Inventory the source artefacts
Identify what is in scope for this run:
gh issue list --state all --limit N per repo.
gh pr list --state all --limit N per repo.
- Sentry project names + date window.
Capture counts and date window in the output header so the verdict
is reproducible.
2. Inspect each artefact and tag
Per artefact, capture:
- Theme tag (free-text, normalised in step 3).
- Author (distinct identity).
- Severity — blocking / friction / wish / praise.
- Segment — derived from the product spine slot.
- Citation —
repo#123, PR URL, Sentry issue ID.
3. Normalise and rank
Cluster theme tags into 5–12 themes max. For each:
- Distinct-author count (the rank key).
- Severity mix (blocking-share matters more than wish-share).
- Recency — last 90 days vs older; weight 2× recent.
- Segment skew — does the theme cluster in one segment?
Drop themes with < 3 distinct authors unless severity is
blocking or the theme is brand-new in the recency window.
4. Build the theme report and validate
One row per theme. Columns: theme · distinct authors · severity
mix · recency · segment skew · representative citations (≤ 3) ·
proposed next step (refine / probe / defer).
Validate the report before handing back: verify each row cites
≥ 1 artefact, check that distinct-author counts match the source
inventory from step 1, confirm no PII leaked into the citations,
and ensure no theme rated defer lacks a written rationale.
5. Surface scope violations
Themes that fall outside the product spine slot's declared scope
go into a scope-violation.md block, never silently into the main
report. The team decides whether to expand scope or close the door.
6. Hand back
Route refine candidates to refine-ticket;
route probe candidates (need live interview) to
discovery-interview; defer the
rest with explicit rationale.
Related Skills
WHEN to use this
- The signal needs to come from existing repo / Sentry artefacts.
- The output is a theme list with citation, not narrative summary.
- A roadmap proposal needs grounded VoC backing.
WHEN NOT to use this
- The signal needs a live conversation — route to
discovery-interview.
- The artefacts are chat-export sourced (Discord, Slack) — refuse
and route to a privacy review (deferred per bounded scope).
- The output is a quantitative funnel — route to
funnel-analysis.
- A theme is already a ticket candidate — route directly to
refine-ticket.
When the agent should load this
- "Was sagen die User wirklich?"
- "Top-Themen aus den letzten 90 Tagen Issues."
- "Welche Sentry-Patterns sind recurring?"
- "Backe der Roadmap-Phase ein VoC-Block dazu."
- "Gibt es ein Segment, das uns überproportional pingt?"
Output
- Header — sources scanned, counts, date window, scope notes.
- Theme report table — themes, distinct authors, severity mix,
recency, segment skew, citations, next step.
- Scope-violation block — themes outside the product spine
slot, explicit, never collapsed into the main table.
- Routing list — refine / probe / defer rows with the named
downstream skill per theme.
Gotcha
- One articulate user can own three themes; rank by distinct authors
or you ship their backlog.
- A theme with no recency (all > 90 days) is archaeology, not VoC;
flag it explicitly.
- Chat-export requests are tempting (Discord copy-paste); refuse
per bounded scope until the privacy review lands.
Do NOT
- Do NOT scrape external sources or hit SaaS APIs the team does not
already own.
- Do NOT surface PII; paraphrase before quoting.
- Do NOT collapse scope-violations into the main table.
- Do NOT lock decisions inside this skill — hand off to
refine-ticket or decision-record.
1---2name: voc-extract3description: Use when extracting Voice-of-Customer themes from existing artefacts — GH issues, PR threads, Sentry patterns. Triggers on 'what are users saying', 'recurring complaints', 'top themes'.4---56# voc-extract78## When to use910- A backlog or planning round needs grounded user-voice signal, not anecdotes.11- A round of bug reports / feature requests / Sentry events has accumulated and the team needs themes with citation per theme.12- A roadmap proposal needs a "what users keep telling us" backing section.1314Do NOT use this skill for live interviews15([`discovery-interview`](../discovery-interview/SKILL.md)) or for16quantitative funnel diagnosis ([`funnel-analysis`](../funnel-analysis/SKILL.md)).1718## Bounded scope1920- **Read-only on artefacts the host already has** — local repo issues21 (`gh issue list`), PR discussions (`gh pr view`), Sentry projects22 the team owns. No external scrape, no SaaS API calls.23- **Chat-export sourcing (Discord, Slack) is deferred** pending24 privacy review (council Q5, SHIP-WITHOUT). If a request asks for25 chat-derived VoC, refuse and route the user to a privacy review.26- **No PII surfacing** — quotes are paraphrased to remove names,27 emails, tenant identifiers; verbatim is reserved for product-team28 artefacts inside the repo.2930## Cognition cluster3132- **Mental model 15 — Signal vs noise.** A loud single reporter33 swamps quiet recurring patterns; rank by **distinct authors**, not34 comment count. See35 [`docs/contracts/mental-models.md`](../../../docs/contracts/mental-models.md) § 15.36- **Mental model 14 — Pareto.** Roughly 20% of themes carry 80% of37 the contact volume; cut the long tail explicitly so the team acts38 on the head. See `mental-models.md` § 14.39- **Mental model 22 — Data-informed, not data-driven.** Issue counts40 are evidence, not voting; weight by recency, severity, and segment41 before recommending. See `mental-models.md` § 22.42- **Product context-spine slot.** Read **product** for segments,43 non-goals, and focal jobs; do not surface themes that fall outside44 the declared scope without a scope-violation flag. See45 [`context-spine`](../../../docs/contracts/context-spine.md).4647## Procedure4849### 1. Inventory the source artefacts5051Identify what is in scope **for this run**:5253- `gh issue list --state all --limit N` per repo.54- `gh pr list --state all --limit N` per repo.55- Sentry project names + date window.5657Capture counts and date window in the output header so the verdict58is reproducible.5960### 2. Inspect each artefact and tag6162Per artefact, capture:6364- **Theme tag** (free-text, normalised in step 3).65- **Author** (distinct identity).66- **Severity** — blocking / friction / wish / praise.67- **Segment** — derived from the **product** spine slot.68- **Citation** — `repo#123`, PR URL, Sentry issue ID.6970### 3. Normalise and rank7172Cluster theme tags into 5–12 themes max. For each:7374- **Distinct-author count** (the rank key).75- **Severity mix** (blocking-share matters more than wish-share).76- **Recency** — last 90 days vs older; weight 2× recent.77- **Segment skew** — does the theme cluster in one segment?7879Drop themes with `< 3` distinct authors **unless** severity is80blocking or the theme is brand-new in the recency window.8182### 4. Build the theme report and validate8384One row per theme. Columns: **theme · distinct authors · severity85mix · recency · segment skew · representative citations (≤ 3) ·86proposed next step (refine / probe / defer)**.8788Validate the report before handing back: verify each row cites89≥ 1 artefact, check that distinct-author counts match the source90inventory from step 1, confirm no PII leaked into the citations,91and ensure no theme rated `defer` lacks a written rationale.9293### 5. Surface scope violations9495Themes that fall outside the **product** spine slot's declared scope96go into a `scope-violation.md` block, never silently into the main97report. The team decides whether to expand scope or close the door.9899### 6. Hand back100101Route refine candidates to [`refine-ticket`](../refine-ticket/SKILL.md);102route probe candidates (need live interview) to103[`discovery-interview`](../discovery-interview/SKILL.md); defer the104rest with explicit rationale.105106## Related Skills107108**WHEN to use this**109110- The signal needs to come from existing repo / Sentry artefacts.111- The output is a theme list with citation, not narrative summary.112- A roadmap proposal needs grounded VoC backing.113114**WHEN NOT to use this**115116- The signal needs a live conversation — route to117 [`discovery-interview`](../discovery-interview/SKILL.md).118- The artefacts are chat-export sourced (Discord, Slack) — refuse119 and route to a privacy review (deferred per bounded scope).120- The output is a quantitative funnel — route to121 [`funnel-analysis`](../funnel-analysis/SKILL.md).122- A theme is already a ticket candidate — route directly to123 [`refine-ticket`](../refine-ticket/SKILL.md).124125## When the agent should load this126127- "Was sagen die User wirklich?"128- "Top-Themen aus den letzten 90 Tagen Issues."129- "Welche Sentry-Patterns sind recurring?"130- "Backe der Roadmap-Phase ein VoC-Block dazu."131- "Gibt es ein Segment, das uns überproportional pingt?"132133## Output1341351. **Header** — sources scanned, counts, date window, scope notes.1362. **Theme report table** — themes, distinct authors, severity mix,137 recency, segment skew, citations, next step.1383. **Scope-violation block** — themes outside the product spine139 slot, explicit, never collapsed into the main table.1404. **Routing list** — refine / probe / defer rows with the named141 downstream skill per theme.142143## Gotcha144145- One articulate user can own three themes; rank by distinct authors146 or you ship their backlog.147- A theme with no recency (all > 90 days) is archaeology, not VoC;148 flag it explicitly.149- Chat-export requests are tempting (Discord copy-paste); refuse150 per bounded scope until the privacy review lands.151152## Do NOT153154- Do NOT scrape external sources or hit SaaS APIs the team does not155 already own.156- Do NOT surface PII; paraphrase before quoting.157- Do NOT collapse scope-violations into the main table.158- Do NOT lock decisions inside this skill — hand off to159 `refine-ticket` or `decision-record`.