| name | kelly-feedback |
| description | Personal App-in-Skill voice-of-customer desk for aggregating user feedback from support email, Discord/Slack communities, X replies, app-store reviews, surveys, and interviews into clustered feature requests and a roadmap decision queue. Use when the user invokes $kelly-feedback or /kelly-feedback, or mentions user feedback, voice of customer, feature requests, roadmap decisions, feedback clustering, feedback triage, request dedupe, changelog replies, decline replies, or reviewing what users are asking for. |
Kelly Feedback
Overview
Use this skill as Kelly's voice-of-customer desk. It aggregates raw user feedback from every channel (support email, Discord, Slack, X replies, app-store reviews, in-app surveys, interviews) into one file-backed App-in-Skill dashboard, where the agent's dedupe/clustering work becomes feature requests with frequency and user weight, and agent-proposed roadmap changes wait in a decision queue for Kelly's verdict.
Division of labor: the skill (scripts + agent) collects, clusters, and drafts; the app is where Kelly triages feedback and decides on proposals; approved roadmap changes are exported/executed by the agent outside the app (updating a roadmap doc or changelog, handing decline replies to kelly-messenger or kelly-email). Kelly Feedback sits downstream of kelly-email, kelly-messenger, and kelly-social: those skills' agents hand feedback payloads to this skill's ingest script.
Default interaction mode: App UI. Unless the user explicitly asks for chat-only handling, check onboarding/config, refresh or load the local feedback snapshot, start/reuse the local app with app/start.sh, and give the actual local URL. Use chat-only mode only when the user says "纯聊天", "chat only", "不要打开 UI", or similar; in that mode present proposals as numbered items (Proposal #1, #2, ...) and record verdicts in decisions.json.
App UI Screenshots
 |  |
Overview Voice-of-customer desk with weekly inflow by channel, sentiment split, top clusters, and source freshness. | Inbox Raw feedback stream across email, Discord, Slack, X, and app-store reviews with triage controls. |
 |  |
Requests Clustered feature requests with frequency, weighted scores, trend, and representative quotes. | Roadmap decisions Agent-proposed promote/decline/merge proposals with drafted changelog notes and user replies for approval. |
Boundary
- Aggregation is local. The skill may read exports/handoff payloads, normalize feedback, cluster it, validate schemas, and write local handoff files.
- The app reads and writes local files only. It must not call feedback platforms, post replies, publish changelogs, or mutate remote systems.
- Any outbound side effect — replying to a user, publishing a changelog note, editing a public roadmap — is approval-required and executed by the agent via other skills (kelly-messenger, kelly-email, docs edits) only after the matching proposal is approved in the decision queue.
- Own-community data only: ingest feedback addressed to Kelly's own products from Kelly's own channels and accounts. Do not scrape third-party communities or collect data about other companies' users.
- Treat feedback as user PII-adjacent. Do not commit
config.local.json, env files, app/.data/, exports, tokens, or raw platform responses.
First Run And Onboarding
On invocation, check app/.data/onboarding.json and private config readiness. If onboarding is absent/incomplete, guide setup before ingesting real feedback.
Private config priority:
KELLY_FEEDBACK_CONFIG=/absolute/path/to/config.json
skills/kelly-feedback/config.local.json
~/.config/kelly-feedback/config.json
skills/kelly-feedback/config.example.json as template only
Env priority:
- Existing environment variables
KELLY_FEEDBACK_ENV_FILE=/absolute/path/to/.env
- Repository root
.env
skills/kelly-feedback/.env.local
~/.config/kelly-feedback/.env
Onboarding asks for non-secret setup details only:
- Products: id, display name, one-line tagline for each product feedback can be about.
- Sources: which channels exist (email/discord/slack/x/appstore/survey/interview), how each is collected (sibling-skill handoff, export, manual notes), and which env var names hold any tokens.
- Scoring weights: plan weights (e.g. free=1, pro=3, team=5), default weight, recency half-life.
- Roadmap lanes (default Now / Next / Later) and, optionally, the path of the roadmap document the agent maintains.
Never ask the user to paste secret values into chat. Secrets belong only in local env files. When setup is complete and the user confirms, write app/.data/onboarding.json:
{
"completed": true,
"completed_at": "ISO timestamp",
"config_version": "1"
}
Local App
Start the dashboard with:
skills/kelly-feedback/app/start.sh
The app uses local HTTP on 127.0.0.1, preferring port 3000 through 4000, or KELLY_FEEDBACK_UI_PORT when set. /api/state reports app: "kelly-feedback".
Required app views:
#/overview: VoC command desk — human-attention panel (roadmap decisions waiting, new uncategorized feedback, requests needing info), feedback-this-week inflow by channel with platform badges, sentiment split bars (inline SVG), top clusters by momentum, and freshness per source.
#/inbox and #/inbox/<feedback_id>: raw feedback stream. Rows show channel badge, user handle, product, one-line preview, sentiment, cluster link, and triage state (new/clustered/ignored/insight). Detail shows the full text, user context (plan, tenure, revenue weight), source permalink, linked request, agent note, and triage buttons (assign to request / ignore / mark insight).
#/requests and #/requests/<request_id>: clustered feature requests with title, product, frequency, weighted score (frequency × user revenue weight), trend arrow, status (candidate/roadmap/declined/needs_info), and linked feedback count. Detail shows the agent-drafted problem statement and proposed spec summary, representative quotes, all linked feedback, an editable effort-estimate field, and decision history.
#/roadmap: decision queue of agent-proposed roadmap changes (promote to Now/Next/Later, decline with drafted reply, merge duplicates) with reason, evidence, editable draft, a Review note textarea, decision buttons (Approve / Request changes / Block), stable refs (Proposal #1), and standard workflow states (needs_review / changes_requested / approved / done / blocked). The current roadmap columns (Now / Next / Later) render read-only below the queue. Decision writes honor agent.lock.
#/settings: sanitized config summary — products, sources (channel + collection method), scoring weights, env readiness booleans, data provider, onboarding state, and recent sync log. Never expose secret values.
Demo mode:
?demo=1 opens a deterministic mock voice-of-customer desk for documentation and screenshots.
?demo=overview, ?demo=inbox, ?demo=requests, and ?demo=roadmap select named mock scenes.
?demo=detail opens a request detail with representative quotes.
lang=en or lang=zh forces UI chrome language for screenshots.
- Demo API responses must never read or write
app/.data/ or any live platform data; demo decisions are in-memory only.
UI language: support English and Chinese chrome with Auto default (persisted override in the sidebar). Keep user quotes, handles, product names, and imported data in their original language.
File Contract
Read references/feedback-schema.md before editing the app, scripts, or any generated JSON.
Primary local files:
app/.data/feedback_snapshot.json: canonical snapshot — sources, raw feedback, clustered requests, roadmap lanes, proposals, derived metrics, sync log.
app/.data/decisions.json: Kelly's verdicts from the UI (proposal approve/request_changes/block with review notes and edited drafts; feedback triage; effort estimates).
app/.data/agent_tasks.json: queued agent work — proposals in changes_requested land here for revision.
app/.data/execution_report.json: latest execute_decisions.ts output with concrete operations.
app/.data/onboarding.json: onboarding completion marker.
app/.data/agent.lock: temporary lock while scripts rewrite files; the app rejects decision writes and disables editing while it exists.
config.local.json: private products/sources/scoring configuration, ignored by git.
Use scripts/validate_ui_schema.ts app/.data/feedback_snapshot.json before relying on a snapshot in the UI. The app shows an empty setup state when no snapshot exists.
Ingestion Workflow
scripts/ingest_feedback.ts is the single write path for raw feedback. Anyone with a payload — sibling skills' agents, platform exports, or manual notes — hands feedback to Kelly Feedback the same way:
- Write a payload JSON file (shape in
references/feedback-schema.md): a source block (source_id, channel, name, collection) plus items[] with stable external_ids, text, user context, and timestamps. Suggested drop location: app/.data/inbox/*.json or any temp path.
- Run
node skills/kelly-feedback/scripts/ingest_feedback.ts <payload.json> [more.json ...].
- The script validates, dedupes by
fb-<source_id>-<external_id> (idempotent re-ingest), merges into the snapshot, updates source freshness and derived metrics, and appends a sync_log entry — all under agent.lock.
Typical handoffs: kelly-email exports support threads mentioning features; kelly-messenger exports Discord/Slack community posts; kelly-social exports X replies. Those skills' agents build the payload from their own data; this skill never reads their private files directly. New items land with triage: "new" and appear in the Inbox and the human-attention panel.
Clustering Workflow
Clustering is LLM work done by the agent; scripts/apply_clusters.ts is the deterministic write path.
- Read the snapshot and pick out
triage: "new" items (and any requests needing re-scoring).
- As the agent, dedupe and cluster: group items expressing the same underlying need, draft or update request records (title, problem statement, proposed spec summary, representative feedback ids, trend), and decide non-request items (
ignored for spam, insight for bugs/patterns worth routing elsewhere).
- Write a cluster-assignment payload (shape in
references/feedback-schema.md) and run node skills/kelly-feedback/scripts/apply_clusters.ts <assignments.json>. The script validates ids, upserts request drafts, links feedback, recomputes frequency and weighted score from the raw stream, and logs the run — under agent.lock.
- When clusters warrant action, draft proposals into the snapshot's
proposals[] (promote/decline/merge/changelog) with reason, evidence, and an editable public draft, then send Kelly to #/roadmap. Items with request_changes verdicts return to the agent via agent_tasks.json; after revision set them back to needs_review.
Roadmap Decision Workflow
- Kelly reviews
#/roadmap: edits drafts, writes review notes, and clicks Approve / Request changes / Block. The app records verdicts in decisions.json (never mutating the snapshot) and enqueues agent_tasks.json entries for change requests.
- Before executing, re-read
decisions.json and run node skills/kelly-feedback/scripts/execute_decisions.ts (dry-run) to produce execution_report.json with concrete operations: update_roadmap (target lane), publish_changelog_note (draft id), send_decline_reply (handoff to kelly-messenger/kelly-email), merge_requests.
- Show Kelly the dry-run summary. After confirmation, run with
--apply: local operations (roadmap lanes, merges, request/proposal statuses) are applied to the snapshot; outbound operations are marked handoff_ready only.
- Execute
handoff_ready operations as the agent via the appropriate skill (send the decline reply through kelly-messenger/kelly-email, update the changelog/roadmap document), then record the outcome back into the snapshot's sync log.
- Poll
agent_tasks.json for revise_proposal tasks; revise drafts per the review note and return proposals to needs_review.
Safety Defaults
- Treat every outbound message (decline replies, changelog posts, roadmap publications) as approval-required, one proposal at a time.
- Never invent feedback or inflate counts; frequency and weighted score must derive from real linked items.
- Keep local content minimal: store trimmed feedback text and safe permalinks, not raw platform API responses or attachments.
- Use stable ids everywhere (
external_id dedupe keys, request ids, proposal refs) so re-ingest and re-execution are idempotent.
- If the schema and UI disagree, stop and fix the schema or UI before executing decisions.