Skip to content
Back to skills

Gather Feedback

ASecurity

Pull and triage user feedback from configured sources into actionable buckets. Use when prioritizing work from user input, before a planning cycle, or when asked "what are users saying?".

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
ai-agentsgobashgitdatabase

Works with

  • cli

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add bakw00ds/yakos --skill gather-feedback --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Gather Feedback?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Gather Feedback
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bakw00ds-gather-feedback/badge)](https://www.skillsdirectory.com/skills/bakw00ds-gather-feedback)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: gather-feedback
description: Pull and triage user feedback from configured sources into actionable buckets. Use when prioritizing work from user input, before a planning cycle, or when asked "what are users saying?".
allowed-tools: Read Bash Grep
argument-hint: "[--since <date>] [--source <name>] [--include-resolved] [--stale] [--output-format markdown|json]"
mode: [gather]
---

# Gather Feedback

## Purpose

Collect user-facing feedback (bug reports, feature requests, support
tickets, survey responses) from configured sources, deduplicate, and
present a triage-ready summary. Reading feedback is a planning input,
not an implementation task — this skill produces a list, not changes.

## Scope

Operates on whatever feedback sources the project configures. The
skill is generic; project-level configuration lists which sources
apply (issue tracker, support tickets, Slack channels, in-app feedback,
etc.). Without configuration, the skill surfaces "no sources configured"
and stops — silent assumption is worse than asking.

NOT in scope: writing replies, changing tickets' state, or doing
anything that mutates the source systems. Read-only by design.

## Automated pass

1. Read project feedback configuration from
   `<project>/.claude/feedback-sources.json` (or equivalent — projects
   define their own location). If absent, surface and stop.
2. For each configured source, fetch entries since the cutoff (default:
   last 7 days; `--since` overrides). **By default, filter to actionable
   lifecycle states only** — for sources that expose a status column,
   default to `status IN ('new','reviewed','in_progress')` (or the
   project-config-mapped equivalent of "not yet closed"). `--include-resolved`
   opts in to already-closed entries — useful for retrospective passes and
   for verifying that the project's auto-resolve hook is firing correctly
   (PandaOS reference: the auto-resolve hook flips status to `resolved`
   when a `web/src/lib/changelog.ts` entry cites `Feedback #<id>`; a
   resolved entry without such a citation is a manual-close worth
   flagging in the audit trail). **`--stale` flips the time window**:
   instead of "entries since the cutoff," it surfaces entries OLDER
   than the cutoff that are still in `status='new'` — the "what fell
   through the cracks?" pile, valuable for quarterly cleanup but
   noisy for weekly runs.
3. **Read attached screenshots / images for visual context.** Many
   feedback sources include image attachments — in-app feedback often
   captures `html2canvas` PNGs, GitHub issues embed images by URL,
   Slack threads carry uploaded files. For each entry whose source
   exposes an image attachment (typical fields: `screenshot_url`,
   `attachments[]`, `media[]` — depends on the source's schema), use
   the Read tool to load the image. Read supports PNG, JPG, and other
   common image formats. Visual evidence is decisive for layout / UX
   / rendering bugs and often resolves the bug/feature/question
   classification on its own. If a screenshot URL is local-fs
   (e.g., a project's own `/uploads/` path), read directly; if it's
   a remote URL (e.g., an imgur/CDN link in a public bug tracker), fetch
   only when the source contract permits and the project's outbound-HTTP
   allowlist includes the host; otherwise default to URL-only logging.
   Never read screenshots from sources outside the configured allowlist —
   that class of read is an SSRF surface. If an image fails to load,
   record the URL + reason in the entry's metadata and continue;
   don't block the rest of the pass on one bad attachment.
4. **Correlate against deploy timeline (regression-window flagging).**
   If the project configuration exposes a release timeline — e.g.,
   `release_timeline_path: web/src/lib/changelog.ts` for projects that
   maintain an in-repo changelog, or a git-log query for tagged release
   commits — flag entries timestamped within 12-24 hours of the most
   recent release. Regression-class bugs cluster in this window:
   feedback that lands within hours of a deploy is high-signal for
   "the deploy broke something" vs feedback that sits for days. Per
   entry, attach `regression_window: true|false` + the version it's
   adjacent to. PandaOS reference: the launchd one-shot regression-
   check pattern (`docs/feedback-reports/regression-check-v<version>-
   <timestamp>.md` is the canonical artifact) is the project-side
   analog; gather can correlate against the most recent such file when
   present, or compute the window directly from changelog timestamps.
   When the project doesn't expose a release timeline, skip this step
   silently and note the gap in the artifact ("regression-window
   correlation unavailable: no `release_timeline_path` configured").
5. Deduplicate across sources — the same issue often gets reported
   through multiple channels. Match on title similarity + reporter
   identity where available. Visually-similar screenshots are a
   strong dedup signal even when titles differ. **Cluster on
   structured metadata** where the source provides it — same
   `page_url` across reporters is a hot cluster; same `app_version`
   across reporters narrows to a release-specific regression; same
   `browser` / `os` / `platform` across reporters narrows to a
   surface-specific bug.
6. Categorize by classification (use the screenshot's visual content
   when present; it often clarifies what raw text leaves ambiguous;
   use structured metadata where the source provides it — `user_role`
   distinguishes admin/internal-tester reports from end-user reports;
   `environment` distinguishes prod from dev/test):
   - **bug** — something is broken
   - **feature** — new functionality requested
   - **question** — needs information, not change
   - **noise** — spam, off-topic, dupe
   - **unclear** — couldn't classify confidently
7. Score by signal. Inputs (combine, don't pick one):
   - **Reporter count** — distinct reporters of the same cluster.
   - **Recency** — newer reports score higher.
   - **Severity keywords** — production, crash, data-loss, blocked.
   - **Screenshot corroboration** — visual bugs with screenshot
     evidence outscore text-only "looks weird" reports.
   - **Reporter role** — admin / internal-tester / pentester reports
     score higher than anonymous-public reports (where `user_role`
     is exposed by the source).
   - **Platform-cluster size** — 5 Safari/iOS users reporting the
     same bug + 0 Chrome users reporting it = Safari-specific
     cluster; the cluster as a whole scores higher than the entries
     individually.
   - **`page_url` cluster size** — multiple reports against the same
     screen indicate a hot spot worth looking at structurally.
   - **Regression window** — entries with `regression_window: true`
     from step 4 score higher (deploy-proximity is a strong "this is
     a regression" signal).
   - **`app_version` distribution** — bugs concentrated in one
     `app_version` are likely release-specific regressions; bugs
     spread across versions are likely longstanding issues.

## Populate kanban board

After the automated pass completes (categories and signal scores assigned),
push each actionable entry onto the kanban board in `<work>/current/kanban.md`.
Skip `noise` entries — they don't belong on the board.

### Category mapping

| Gather category | Kanban `--category` |
|---|---|
| bug | `bug` |
| feature | `feature` |
| unclear | `question` |
| question | `question` |
| (maintenance / debt items) | `chore` |
| anything else | `other` |

### Dedup token

Every card title must embed a stable source reference token of the form
`[src:<source>:<id>]`, where `<source>` is the configured source name and
`<id>` is the entry's native ID from that source. Example:
`Login crash on Safari [src:github:4821]`.

**Before adding a card, grep the kanban file for the token:**

```sh
grep -qF '[src:github:4821]' "$(yakos_current_dir)/kanban.md" \
  && echo "already present — skip" \
  || yakos kanban add "Login crash on Safari [src:github:4821]" --category bug
```

If the token is already in the file (in any column, any card), skip that
entry entirely. Do not update or move existing cards — the operator owns
column placement. This keeps re-runs fully idempotent without a database.

### Notes field

After adding a card, set its notes via `yakos kanban notes <id> "<text>"`.
Pack three things into the single line (keep it short):

```
src:<source>:<id> | status:<entry-status> | score:<signal_score>
```

Example: `src:github:4821 | status:new | score:0.87`

If the entry is flagged `regression_window: true`, append ` | regression`
so the operator can spot it without opening the full artifact.

### What to skip

- `noise` entries — don't add them.
- Entries whose dedup token already appears in `kanban.md` — skip silently.
- New cards always land in TODO. Do not call `yakos kanban move` or
  `yakos kanban done` — column triage belongs to the operator.

## Manual pass

The invoking agent reviews the categorization for false categorizations
(LLM classification is fallible) and re-categorizes as needed. Then
prioritizes for action:

- Which bugs need an incident response now?
- Which features fit the upcoming planning cycle?
- Which questions need a doc update vs an individual reply?
- For entries flagged `regression_window: true`: do the recent commits
  on `main` (post-the-correlated-release) explain the report, or is it
  a real regression that needs a hotfix?
- For platform-clusters (Safari-only, iOS-only, etc.): is there a
  shared root cause, or are these unrelated reports that happen to
  coincide on a surface?

**Auto-resolve audit (when `--include-resolved` is set):** for each
resolved entry returned, check whether the resolution is cited in
the project's changelog (e.g., a `Feedback #<id>` trailer in
`web/src/lib/changelog.ts` or git-commit body). When the project's
auto-resolve hook is functioning, every resolved entry should be
cited. Missing citations = manual close (no changelog reference) —
not necessarily wrong, but worth flagging in the artifact for the
audit trail. A run of resolved-without-citation entries usually
means either the auto-resolve hook regex is broken or someone is
hand-closing tickets without writing the fix into the changelog.

## Findings synthesis

Default output is markdown (human-readable). `--output-format json`
emits the same data as a structured array suitable for downstream
skill chaining (e.g., `pre-release-audit` or `phase-complete`
consuming gather output).

### Markdown output (default)

```
Feedback gathered: <n> entries from <m> sources, <date> to <date>
                   (<k> with screenshots read, <j> screenshots failed to load)
                   (<r> in regression window of v<version>, deployed <iso-timestamp>)
  bug:      <n> (<n> high-signal, <n> with corroborating screenshot, <n> in regression window)
  feature:  <n> (<n> high-signal)
  question: <n>
  noise:    <n>
  unclear:  <n>

Top platform clusters:
  Safari/iOS:   <n> entries
  Chrome/Web:   <n> entries
  ...

Top page_url clusters:
  /checkin:     <n> entries
  /clients/:id: <n> entries
  ...

Top 5 by signal:
  <id> | <category> | <signal-score> | <one-line summary> | [📷] [⚠ regression] [<role>] [<platform>]
  ...
```

### JSON output (`--output-format json`)

Schema (locked; downstream consumers can rely on it):

```json
{
  "gathered_at": "ISO-8601 timestamp",
  "since": "ISO-8601 or relative",
  "until": "ISO-8601",
  "sources": ["source-name", ...],
  "release_timeline": {
    "most_recent_version": "<version-or-null>",
    "deployed_at": "ISO-8601 or null",
    "regression_window_hours": 24
  },
  "counts": {
    "total": 0,
    "with_screenshots": 0,
    "screenshots_failed": 0,
    "in_regression_window": 0,
    "by_category": { "bug": 0, "feature": 0, "question": 0, "noise": 0, "unclear": 0 },
    "by_status": { "new": 0, "reviewed": 0, "in_progress": 0, "resolved": 0, "dismissed": 0 },
    "by_platform": { "...": 0 },
    "by_app_version": { "...": 0 }
  },
  "entries": [
    {
      "id": "source-native id",
      "source": "source-name",
      "category": "bug|feature|question|noise|unclear",
      "status": "new|reviewed|...",
      "signal_score": 0.0,
      "regression_window": false,
      "regression_window_version": null,
      "screenshot_url": null,
      "screenshot_loaded": false,
      "metadata": {
        "app_version": "...",
        "user_role": "...",
        "platform": "...",
        "browser": "...",
        "os": "...",
        "environment": "...",
        "page_url": "..."
      },
      "title": "...",
      "summary": "...",
      "reporter_count": 1,
      "auto_resolve_cited": null
    }
  ]
}
```

Each entry retains its original ID and source for traceability — no
fields are paraphrased into oblivion. Entries with screenshots
include the screenshot URL/path in the artifact so a human reviewer
can re-open the image without re-running the gather pass.

## Known gotchas

- Classification quality depends heavily on the source format.
  Free-form support tickets classify worse than structured bug reports.
  When in doubt, mark "unclear" — over-eager classification poisons
  triage.
- Customer feedback often contains sensitive data (PII, account info).
  This skill is read-only, but the artifact it produces lands in
  `work/current/artifacts/` — treat that artifact as sensitive too.
  **Screenshots routinely contain more sensitive data than the text:**
  visible names, email addresses, account balances, partial card
  numbers, in-app PII fields, etc. The artifact records the URL/path
  to each screenshot but does NOT inline the bytes — readers must
  re-open the image with the same sensitivity classification as the
  feedback itself.
- Feedback "score" is a heuristic, not truth. A single high-quality
  report from a knowledgeable user can outweigh 50 vague tickets.
- The skill respects `--since`; without it, default of 7 days is fine
  for a weekly cadence but wrong for a quarterly review.
- **Screenshot reads are part of the gather pass, not optional.** A
  feedback entry triaged without its screenshot is a partial read —
  layout / rendering / UX bugs in particular cannot be classified
  reliably from text alone. If a project's source format exposes
  attachments and the gather skill skips them, mark the gap in the
  artifact + raise it as a configuration issue rather than silently
  proceeding.
- **`--include-resolved` is for retrospective passes only**, not the
  default daily/weekly cadence. Including resolved entries on every
  run clutters triage with already-actioned items; use the flag
  only when verifying the auto-resolve hook is firing correctly or
  when reviewing a closed batch (e.g., post-release retrospective).
- **`--stale` is for periodic cleanup**, not weekly cadence (step 2 flips
  the time window). Run quarterly (or before a planning cycle) to force-
  decide each entry: action / dismiss / dedup / accept-as-known. Weekly
  runs are noise: the answer to "why are these still here?" is usually
  "because nobody triaged them last week either."
- **Regression-window correlation requires a release timeline.**
  When the project config doesn't expose `release_timeline_path` or
  equivalent, step 4 is skipped silently and the artifact records
  "regression-window correlation unavailable." This is a
  configuration gap, not a skill bug — surface it in the manual
  pass + ask the project owner to expose the timeline.
- **JSON output schema is locked.** Downstream skills (e.g.,
  `pre-release-audit`, `phase-complete`) rely on the schema in the
  Findings synthesis section. Adding new fields is fine (additive);
  removing or renaming requires a deliberate version bump in the
  schema header (currently implicit v1; bump to v2 explicitly when
  breaking).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…