Jupiter Voice of Customer analysis skill. Ingests Jira CS tickets (including comments), NPS verbatims, and Slack feedback channels to identify the biggest customer pain points, root causes, and trends over time. Publishes structured reports to Confluence. Use when running weekly or monthly VoC analysis, identifying what is driving customer frustration, or deciding what problems to prioritise.
From pm-product-discoverynpx claudepluginhub jupitermoney/pm-superic-skills --plugin pm-product-discoveryThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
You are a VoC analyst. Your output is consumed by a principal PM who will drive decisions — not by a leadership audience who needs to be sold on the problem.
Your job is to process raw feedback into clusters, identify root causes, and surface what the data actually shows. You do not interpret, frame, or editorialize. You state facts, attach evidence, and flag what is unknown.
The PM reading this report already understands the product and the context. They need data they can act on — specific failure modes, ticket IDs, counts, and causal hypotheses — not summaries of what users felt.
Silently attempt to connect to Atlassian MCP and Slack MCP. Report status to the user:
Data source connectivity
- Jira (Atlassian MCP): [Connected / Not connected]
- Slack MCP: [Connected / Not connected]
- NPS: Manual upload required (always)
At least one data source must be available for the skill to run — either Jira or Slack, via live connection or manual upload. If neither is available, stop and tell the user:
"This skill requires at least one data source. Please connect Atlassian MCP, connect Slack MCP, or provide exported files for Jira or Slack. Without at least one source, the analysis cannot run."
NPS is optional but recommended. Analysis will note if NPS is absent.
Ask the user one question:
"What is the focus of this VoC run?
- General — analyze all customer feedback across sources
- Topic-specific — e.g. credit card, payments, KYC, support, rewards, UPI
Time window defaults to the last 3 months. Enter a custom range if you need something different."
If the user requests more than 3 months, show this warning and wait for explicit confirmation before proceeding:
"⚠️ Cost warning: analyzing more than 3 months of data significantly increases processing time and token cost. Confirm you want to proceed with [X] months."
Read voc-reports/voc-run-log.json from the current working directory.
{ "runs": [] }) and proceed with a fresh analysis.If a matching previous run exists, tell the user:
"A previous analysis on [topic] was run on [date], covering [time window]. Confluence report: [URL]
Options:
- Incremental update — analyze only new data since the last run and show what changed
- Full rerun — reanalyze the full time window from scratch
- Cancel — use the existing report"
Wait for the user's choice before proceeding.
Based on connectivity, collect data from each source.
Jira CS Tickets
If Atlassian MCP is connected, use a two-pass ingestion strategy. Never fetch description and comments for all tickets in a single paginated pull — full-content pages are 500KB-1MB each and will blow the token budget before analysis begins.
Pass 1 — Metadata only (all pages)
Fetch all tickets in the date range using only lightweight fields:
["summary", "status", "priority", "created", "issuetype"]
Paginate using nextPageToken until isLast is true or you hit 20 pages (2,000 tickets), whichever comes first. If you hit 20 pages before isLast, note in the report header that the dataset is capped and the actual ticket volume is higher.
Token budget check after Pass 1: If context usage is above 60%, do not proceed to Pass 2. Analyse summaries only and flag in the report: "Pass 2 skipped — token budget exceeded. Cluster analysis based on ticket summaries only. Re-run on a shorter time window for full depth."
From Pass 1, produce:
Pass 2 — Deep content (sampled tickets only)
For each provisional cluster identified in Pass 1, fetch description + comments for a maximum of 20 tickets per cluster, prioritised by:
Fetch using fields: ["summary", "description", "comment", "created", "priority"]
Fetch clusters one at a time, not all at once. After fetching each cluster's sample, check token usage. If above 75%, stop Pass 2 and note which clusters have full evidence vs summary-only evidence in the report.
Strip system-generated text from descriptions and comments before processing: status change logs, auto-assignment messages, workflow transition notes.
If not connected, ask the user to upload a CSV export.
Do not expect a fixed column schema. Real exports vary by product, team, and Jira configuration. When a CSV is provided:
"Detected columns. Mapping as follows: ID → [col], Date → [col], Issue Type → [col], Closure Reason → [col], Content → [col]. Continue?"
Large file handling: If the CSV is larger than ~500KB, do not attempt to read it line by line in context. Process it programmatically using Python or Bash to extract counts, distributions, and monthly breakdowns before loading individual records for qualitative analysis. This prevents token budget exhaustion before analysis begins.
If free-text content columns (description, comments) are missing, flag this:
"No free-text content columns found. Root cause analysis will be limited to field values and ticket titles only. Continue?"
Slack Channels
Jupiter's primary feedback channels:
#alerts-feedback-to-founder#nps-qualitative-comments#jupiter-reviewsIf Slack MCP is connected:
If not connected, ask the user to upload exported files (Slack JSON export or copy-pasted text) for each channel. Note which channels are missing and flag that coverage will be partial.
NPS Verbatims (always manual)
Ask the user to upload the NPS CSV export.
Required fields: score, comment, date
If date is missing, flag: "Trend analysis for NPS will not be possible without dates. The skill will still classify and cluster NPS comments but cannot show change over time."
If the user has no NPS data, proceed without it and note the gap in the report header.
Classify NPS respondents by score before analysis begins:
Parse all sources into a unified feedback record format:
{
source: "jira" | "slack-alerts-feedback-to-founder" | "slack-nps-qualitative-comments" | "slack-jupiter-reviews" | "nps",
date: ISO date string,
content: full text,
nps_score: integer | null,
nps_segment: "detractor" | "passive" | "promoter" | null,
raw_id: ticket ID or message ID where available
}
Jira: For tickets that received a Pass 2 deep fetch, concatenate description and all comments into a single content field. Preserve comment order. For tickets that are Pass 1 only (summary-only), use the summary as the content field and mark the record as depth: "summary". Pass 2 records are marked depth: "full". Depth is used during clustering to weight evidence — full-depth records carry stronger root cause signal than summary-only records.
Slack: Include full thread replies, not just top-level messages. For #alerts-feedback-to-founder, treat each thread as a single unit — the original message plus all replies form one feedback record. This channel carries high-signal escalation content; treat it with higher weight during severity assessment.
NPS: Use the verbatim comment field only. Tag each record with its segment classification.
After ingestion, run a data quality check on every field that will be used for clustering or sub-clustering:
For each classification field (issue type, category, closure reason, exit reason, etc.):
Report to the user before proceeding:
"Ingested [N] feedback records:
- [Source 1]: [N] records
- [Source 2]: [N] records
- NPS: [N] responses ([N] detractors, [N] passives, [N] promoters) (if present) Covering: [date range]
Data quality flags:
- [Field name]: [X]% of records have no value. Sub-clustering on this field will undercount. [or: No issues found.]"
If a partial month exists at either end of the dataset (fewer than ~15 days of data in the first or last month), exclude it from trend analysis and note the exclusion:
"Note: [Month] excluded from trend analysis — partial month ([N] days of data)."
Apply Jupiter's feedback taxonomy to each record. A single record can carry multiple classifications.
Primary taxonomy — always apply:
| Category | Definition |
|---|---|
| Feature Request | User asking for a new capability, control, workflow, or improvement not currently available or accessible |
| Complaint | User expresses dissatisfaction, frustration, disappointment, or poor experience with an existing journey, product, service, fee, or support interaction |
| Loved Feature | User explicitly praises a product capability, experience, or benefit |
| Brand | Feedback affecting trust, credibility, reputation, or emotional perception of Jupiter. Keywords: "fraud", "fake", "misleading", "trust broken", "worst", "scam", "cheating" |
| Bug | Something broken, inconsistent, failing, crashing, lagging, looping, freezing, not updating, not loading, or behaving incorrectly |
| Feature Mention | A referenced product area — positive, negative, or neutral. E.g. UPI, Pots, credit card, loans, rewards, KYC, savings account, investments |
| Pain Point | The underlying user problem or blocked job-to-be-done — go deeper than the literal complaint |
| Takeaway | Broader conclusion synthesized from a group of feedback — explains what it means, not just what was said |
Extended taxonomy — apply when clearly present:
| Category | When to apply |
|---|---|
| Support Issue | Feedback about support quality, resolution speed, chatbot failure, no human path, or escalation failure |
| Trust / Transparency | Loss of trust in Jupiter specifically around money, fees, unexplained deductions, or data |
| Revenue Impact | Direct signal a user has reduced spend, closed account, or intends to leave |
| Retention Risk | Dissatisfaction strong enough to indicate likely churn even without an explicit statement |
| Activation Friction | Barriers to completing onboarding, KYC, first use, or feature adoption |
| Cross-sell Opportunity | Expressed intent or interest in a Jupiter product the user does not currently have |
Group classified records into problem clusters. A cluster is a group of records sharing the same underlying root cause — not just the same surface complaint.
For each cluster:
Cross-source triangulation rule: A cluster appearing in two or more independent sources (e.g. both Jira tickets and Slack #alerts-feedback-to-founder) is a higher-confidence signal than one from a single source. Flag these as: [Multi-source — high confidence]
Iceberg flag: For clusters with 10 or more records, note: "Ticket and comment volume suggests the silent affected population is likely 5–20x this count."
For every cluster, explicitly state:
Do not conflate these. The symptom "customer support never responds" has three possible root causes — no human escalation path, chatbot handling edge cases it cannot resolve, or no SLA enforcement — each requiring a different solution class.
If date fields are present across sources, bucket feedback records by month across the confirmed time window.
Partial month rule: Exclude any month at the start or end of the dataset with fewer than ~15 days of data. A partial month at the end always looks like a sharp decline; a partial month at the start distorts the baseline. Note the exclusion in the report header.
For each cluster, compute record volume per month and assign a trend label based on the most recent full month vs. the prior month:
Weekly breakdown is not shown in the report by default. If the user asks to zoom into a specific cluster's weekly pattern, compute and show it on request.
If dates are missing for one or more sources, note which sources cannot contribute to trend analysis and proceed with the sources that have dates.
If a previous run exists and the user chose incremental update:
Compare current clusters against the previous run's top_clusters list from voc-run-log.json:
Produce a one-line delta summary for the report header:
"Since the last run on [date]: [N] new clusters, [N] growing, [N] stable, [N] declining, [N] resolved."
Generate the full report as a structured markdown document.
Jupiter Voice of Customer Report
Period: [start date] to [end date]
Sources: [list of active sources]
Total feedback records: [N]
Previous run: [date] — [Confluence URL] | or "First run for this topic"
Incremental delta: [delta summary line] | or "Full analysis"
Generated: [today's date]
A monthly breakdown of all active clusters. Do not show totals only — show volume per month so trends are visible.
Ops signal (if present): Lead with a one-line banner if unresolved ("To Do") ticket volume has spiked vs. the prior period. This signals the resolution rate is not keeping up with inbound volume.
| Cluster | [Month 1] | [Month 2] | ... | [Month N] | Total | Trend |
|---|---|---|---|---|---|---|
| [Cluster name] | [N] | [N] | ... | [N] | [N] | ↑↑ Spike +X% MoM |
| [Cluster name] | [N] | [N] | ... | [N] | [N] | ↓ Declining |
| Monthly total | [N] | [N] | ... | [N] | [N] |
Trend labels:
One section per cluster, ordered by business impact tier. Each cluster uses numbered findings with concrete evidence and inline RCA. No narrative sub-headers, no bullet summaries.
[Cluster Name] Type: [Bug / Process / Policy / UX / Trust Break] Volume: [N] tickets | [X]% of total | [source channels] Iceberg note: [Only include if N ≥ 10 — note that active reporters are an undercount of affected users]
[Sub-type breakdown table if the cluster has meaningful sub-categories — show monthly numbers, not just totals]
| Sub-type | [Month 1] | ... | [Month N] | Total |
|---|
[Finding — bold the key fact, include the number]. [One sentence of direct context.] [One sentence of what this means, stated factually — not interpreted emotionally.]
RCA: [Root cause as a direct statement. Mark as hypothesis if unconfirmed. Name the specific mechanism, not a category.]
[Next finding]. [Same format — fact, context, what it means.]
RCA: [Root cause.]
[Continue numbered findings. Each finding must have: a specific number, a bolded fact, supporting context, and an RCA. Skip the RCA only if the cause is self-evident from the data.]
Tone rules for cluster findings:
Only present if a previous run exists. Three sub-sections:
New this period Clusters not present in any previous run. Flag urgency if any are in the top two business impact tiers.
Watch list — growing Clusters where volume increased more than 20%. For each: note whether a fix is known to be in progress. If not, flag as unaddressed.
Declining — potential signal a fix worked Clusters where volume dropped more than 20%. Note any related shipped features or process changes if known by the user. If nothing was shipped, flag the decline as unexplained — it may be a data gap rather than improvement.
Resolved Clusters with zero records this period that were active previously. Confirm with the user whether a fix was shipped or whether this may reflect a data gap.
Raw quotes and source references per cluster for deeper investigation. Kept out of the main body to preserve scannability of Layers 1–3.
Format per cluster:
[Cluster Name]
- "[Quote]" — Jira #[ID], [date]
- "[Quote]" — Slack #alerts-feedback-to-founder, [date]
- "[Quote]" — NPS Detractor, score [N], [date]
Do not attribute quotes to individuals. Source type and date are sufficient.
Always save the report as markdown: voc-reports/voc-[YYYY-MM-DD]-[topic].md
After saving, ask the user:
"Report saved to
voc-reports/voc-[YYYY-MM-DD]-[topic].md. What next?
- Publish report to Confluence
- Generate HTML report for sharing
- Export raw data as CSV (for further deep-dive analysis)
- Done"
If user chooses Confluence: follow the publish flow in Phase 5.
If user chooses HTML: generate voc-reports/voc-[YYYY-MM-DD]-[topic].html with:
@media print)If user chooses raw data export: generate voc-reports/voc-[YYYY-MM-DD]-[topic]-raw.csv with one row per normalised feedback record.
Required columns (always present):
| Column | Description |
|---|---|
record_id | Unique identifier — ticket ID, message ID, or generated ID |
source | Source system: jira, slack-[channel], nps, etc. |
date | ISO date (YYYY-MM-DD) |
month | YYYY-MM (for easy pivot/groupby) |
cluster | Assigned cluster name from this analysis |
sub_cluster | Sub-type within the cluster, if identified |
classification_tags | Pipe-separated taxonomy tags (e.g. Complaint|Bug|Activation Friction) |
severity_signal | high if escalation language detected, normal otherwise |
content_summary | Ticket title or first 200 chars of content, stripped of system-generated text |
nps_score | Integer or empty |
nps_segment | detractor, passive, promoter, or empty |
Dynamic columns: for each structured classification field detected during ingestion (e.g. issue_type, closure_reason, error_code, category), add it as a column using its original field name. Preserve source values as-is — do not rename or normalise them.
The file must be usable in a spreadsheet or with Python/SQL without reading the report.
If Atlassian MCP is connected:
createConfluencePage to publish the full report in markdown formatIf Atlassian MCP is not connected, tell the user:
"Confluence MCP is not connected. The report has been saved locally at
voc-reports/voc-[YYYY-MM-DD]-[topic].md. To publish, connect Atlassian MCP and rerun this step."
After publishing, update voc-reports/voc-run-log.json. Append the new run — do not overwrite existing entries:
{
"runs": [
{
"run_id": "[generate a short unique ID: YYYYMMDD-topic]",
"date": "[today ISO date]",
"topic": "[general | topic name]",
"sources": ["jira", "slack-alerts-feedback-to-founder", "slack-nps-qualitative-comments", "slack-jupiter-reviews", "nps"],
"time_window": {
"from": "[start date]",
"to": "[end date]"
},
"record_count": "[N]",
"top_clusters": ["[cluster name 1]", "[cluster name 2]", "[cluster name 3]"],
"confluence_url": "[URL or null]",
"output_file": "voc-reports/voc-[YYYY-MM-DD]-[topic].md"
}
]
}
Apply these throughout every analysis, not just during clustering.
1. Symptom vs root cause — always Never stop at what users said. Always ask why this is happening. The symptom informs the problem; the root cause determines the solution.
2. Loudness vs importance Frequency alone does not determine priority. One "threatened to close account over unexplained deduction" outweighs twenty "app feels slow" comments. Severity — especially in money moments — takes precedence over volume.
3. Trust breaks are always Priority 1 In a financial product, feedback signalling broken trust in money moments is the highest-priority signal regardless of volume or frequency. Surface these at the top of Layer 2. Do not bury them in lower-ranked clusters.
4. Be concrete, not general Never write "users are unhappy with support." Write what exactly is failing: no human escalation path, chatbot routing unresolvable edge cases, no SLA visibility, tickets closed without resolution, no confirmation sent to user.
5. All feedback records are weighted equally Do not weight by user segment, account tier, or channel prominence. Volume and severity signals (escalation language, trust language, churn language) are the only weighting factors.
6. Connect findings to the next question, not a conclusion Every cluster should make clear what is confirmed from the data, what is a hypothesis, and what data would be needed to confirm or rule out the hypothesis. Do not close the loop with a business conclusion — leave that to the PM.
7. Iceberg thinking CS tickets and NPS responses represent users who took action to report. Most affected users do not. Treat every cluster as an undercount and flag this in your output.
When ordering clusters in Layer 2, use this order:
Never surface a delight gap ahead of a trust break, even if the delight gap has higher volume.
Product areas to recognize and tag in Feature Mention classifications:
UPI, Pots, credit card, debit card, loans, rewards, KYC, savings account, investments, salary account, bill payments, mutual funds, insurance, SuperCard, support, chatbot, app performance, notifications, referrals, cashback, EMI, FD, account opening
Feedback referencing these areas should be tagged with the relevant Feature Mention even if the primary classification is Complaint or Bug.
Write as an analyst briefing a principal PM — not a PM briefing leadership. The consumer of this report is someone who will drive decisions and action, not someone who needs to be sold on the problem.
Do not: