- name
- review-latest-feedback
- description
- Review Slack, GitHub, CI, Sentry, Analytics, diagnostics, linked trackers, and app/template, desktop, and package deploy/release lanes. Answer reporters first; fix verified defects, verify delivery, build upvoted features, and recap. Use for scheduled or manual sweeps.
- user-invocable
- true
- scope
- dev
- metadata
- {"internal":true}
# Review Latest Feedback
Four phases, in order. Phase 0 comes before any investigation, not after.
0. **Gate, then claim** every eligible item you intend to tackle with `👀`,
before investigating any of it.
1. **Answer the people who answered you.** Older open questions first.
2. **Fix** what the evidence actually proves, at the owning boundary.
3. **Reply** with useful questions, then recap.
Output is fixes. Reply in-thread for every workflow reaction added this run;
continuing work gets a concrete progress reply, and resolved work gets a final
reply after verification. Follow
[`slack-reaction-replies.md`](references/slack-reaction-replies.md).
## Slack channels
Default channels: `#product-agent-native-feedback` (`C0ATH3CCZT4`),
`#qa-agent-native` (`C0C4U4XRT6X`), and
`#dev-agent-native-feedback` (`C0AJ5QV0J03`). Apply the full workflow to each:
use its `in:<#CHANNEL>` filter for searches and read each channel. Track
pagination, reply cursors, and counts separately. Honor narrower invocation
scope. Each channel uses the same five-day scan boundary; `#dev-agent-native-feedback`
is a default input, not a special-case exclusion.
## Slack ownership gate
Before reading Slack, inspect message and parent reactions. Skip checkmarks and
`👀` owned by another task, including replies and linked work. Only the active
task named in status may resume its own `👀`: verify ownership, reread thread
and reactions, then continue only its scope. Handoffs require the current
owner's explicit reply naming the new task and scope. Claims never expire. Ask
Steve if ownership is unclear; stop if another mark appears. For continuing
work, post one status reply with task link and remaining scope.
## Phase 0: claim what you are taking
Resolve known duplicate clusters before claiming. For an eligible item, add
`👀` before investigation and never remove it. Do not resume items excluded by
the Slack ownership gate. Post **In progress** only when work continues beyond
this run.
**Fix defects or ask directly for the exact reporter-only fact or action
needed to unblock the next step.** If reporter input gates progress, state the
specific question and why. Never substitute **Open**, a symptom recap, a
source-access note, or a vague details request for the ask. Without a reporter
gate, ask no filler: continue internal investigation or fix, then report the
concrete action when a reply is due. Inspect supplied logs and evidence
yourself; never ask for IDs or tool details already given.
A reporter's proposed remedy may be wrong while the bug is real. Trace the
failure to its owner.
Record each symptom's disposition; subjective or out-of-scope feedback
doesn't close a separate defect. Tie each reaction to the scope it marks.
### Reaction gate
`👀` is claim history; `✅` requires **Fixed** after Phase 2 bars. Check each
reported symptom separately. For partial fixes, pair `✅` for verified scope
with `🎫` for any distinct unfinished scope that needs a human to take
ownership or act, whether or not a ticket exists. Link a verified ticket and
name its owner/action; without one, keep the handoff explicit in the reply and
ledger and say that an owner or ticket still needs to be assigned. Do not
create or promise a ticket without authorization. No `🎫` for fixed scope,
routine rollout, optional checks, subjective/out-of-scope, or unapproved work.
**Shipped**/**Live verified** alone don't earn `✅`. Never remove reactions.
Follow the reply reference before marking an item replied.
Before recording an evidence limit or asking, try to reproduce the defect from
the supplied artifact, URL, error, run ID, or logs. Investigate our access,
config, observability, and deployment gaps. For each defect, continue internal
work unless one reporter-only fact changes the next action; then ask one direct
question naming the fact and why it gates progress. Never request supplied
evidence, generic details, or answers to unrelated questions. Without a
reporter gate, state the internal action and owner. After four days unanswered,
record **Abandoned - no answer in 4 days**.
For supplied run IDs, query Thread Debug for exact events and tool results. If
unavailable, query the app's first-party Analytics by exact ID for tool calls,
model requests, and errors. Dispatch status or an empty failed-run list is not
an exact trace. Try both sources before recording the lookup error. Never ask
for supplied IDs, logs, or tool details, and do not infer the run is absent.
Use **Skipped** only for non-defects. **Open - no question** is ledger-only:
name the internal next action and owner; never send it as a Slack reply.
### Authoritative disposition vocabulary
For eligible items, use one disposition per row; record it in the recap and, if
unstated, in the thread or linked work. Do not inspect gated items for status.
For clusters, post one owner status with each source permalink and
**Clustered**; do not mark duplicate non-owners separately. Give a distinct
question or update its own reaction and reply.
- **Terminal (keep this workflow's eye):** **Fixed**, **Shipped**, **Live
verified**, **Open - no question**, **Resolved elsewhere**, **Skipped**,
**Clustered**, or **Abandoned - no answer in 4 days**. Apply the reaction
gate above.
- **Active (retain 👀):** **Verified locally**, **Built - live unverified**,
**Deployed - live unverified**, **Not reproducible - attempted**, or
**In progress**.
- **Waiting on reporter (retain 👀):** **Asked**, **Clarification needed**, or
**Blocked on reporter**. Find these through Phase 1's question search.
- **Owned elsewhere:** use only for an unmarked item when accessible evidence
confirms an active owner; marks owned by another task are skipped by the
ownership gate.
After merge, mark **Fixed** when the source fix is verified. Track
release/runtime separately; normal rollout and optional live checks neither
reopen it nor warrant `🎫`. Follow up only on accepted work outside this run;
record source, target, owner, exact action, and verification. Don't reopen
closed fixes.
**Clustered** closes one row but retains it.
Enumerate channel parents newest-first for five days. For a permalink plus
newer scope, follow the [checked inventory procedure](references/channel-inventory.md).
**`slack_search` can rank and truncate.** Use channel reads to enumerate parents
and put their count in the recap. Sort targeted searches oldest-first and follow
`next_cursor` until exhausted.
Search hits are often replies; resolve `thread_ts` and check parent reactions
before reading the hit or opening the thread.
Read back each new `👀` once. Resume only through the verified owner or handoff
above; never resume checkmarked items.
Claiming does not investigate. Read back new claims. Do not claim out-of-scope
items. If a current-run claim proves out of scope, keep `👀` and post **Skipped**
once without a question. New evidence or upvotes never override the ownership
gate.
Record eligible claims and dispositions; report gated skips in aggregate only.
Cluster fresh repeats for Phase 2.
### External trackers are evidence, not status
For a supplied spreadsheet, export, test matrix, or tracker, read metadata then
the bounded range with its named connector. Enumerate every row and its
completion status; retain its id, reporter, symptom, status, retest, and source
link.
Status, reactions, a merged PR, a source diff, or a unit test is not behavior
proof. Each row needs a post-change ledger result. If it cannot be read, say
**tracker unavailable**, never "no matches."
## Phase 1: answer the people who answered you
Answer eligible questions first; the ownership gate excludes prior-run marked
questions, even if a reporter has since replied.
Slack is the ledger; a per-run state file cannot carry state across runs. First,
exhaust this search to enumerate prior questions and context:
```
slack_search: "this was sent from a bot." in:<#CHANNEL>
sort=timestamp sort_dir=asc include_context=true max_context_length=300
```
Keep context and exhaust pages; include human replies regardless of
punctuation. Open only eligible threads with a human reply.
**The parent is the permalink's `thread_ts`.** `Message_ts` is your own
reply's timestamp; acting on it targets the wrong message.
Find replies even when their parent is older than the five-day scan. Read this
channel's prior reply-scan cursor; without one, scan all available history. A
new reply can belong to an old disclosure, so search all channel messages over
an overlapping date window instead of cursor-filtering the disclosure search:
```
slack_search: in:<#CHANNEL> after:<YYYY-MM-DD>
sort=timestamp sort_dir=asc
```
Filter hits by their timestamp, resolve parent `thread_ts`, and check reactions
first. Skip marked parents without opening threads. Never filter by the older
parent timestamp; `after:` is date-only, so start a day earlier and exhaust
pages. Advance the cursor to the greatest processed hit.
Count a question answered only when a person posts after it without this
workflow's disclosure marker; read the thread to reject partial, unrelated, or
deferred replies. Count each answer once; only a newer message reopens it.
Enumerate answered threads before new work and recap the count. Keep unanswered
**Clarification needed** pending until answered, resolved, or four days old;
other dispositions do not substitute. Reapply Phase 0 eye/checkmark rules.
Apply the age branches only to unanswered **Clarification needed** threads;
restore any such thread mistakenly marked **Open - no question**.
- **Someone answered** → highest priority in the run, ahead of every newer
report: the evidence you said blocked you now exists. Rebuild it and attempt
the fix. Reply **Fixed** only after all four bars pass; otherwise keep the
clarification open. Never ask a follow-up before trying the fix.
An answer that the issue is already resolved, fixed elsewhere, or not ours —
a linked PR, "not a Clips issue" — is still an answer. Close it as
**Resolved elsewhere** (terminal, and distinct from **Skipped**, which means
out of scope): keep our `👀` and record who resolved it and where. The
participant's reply is the status; do not add `✅`.
- **No answer, posted under 4 days ago** → leave it. Post nothing. A second
message is a nag, not a follow-up.
- **No answer, posted over 4 days ago** → the question failed. Do not remind or
re-ask. Keep the `👀`, record **Abandoned - no answer in 4 days** once in the
thread without a new question, and carry any still-relevant bug forward as an
internal investigation.
Search without `after`, then apply the four-day expiry; disclosure is the
cross-identity cursor. For legacy replies without disclosure or eyes, run once
per valid workflow identity:
```
slack_search: from:<EACH_WORKFLOW_IDENTITY> in:<#CHANNEL>
sort=timestamp sort_dir=asc
```
Classify these hits by clarification wording (for example, `if you can share`),
not as the discovery cursor. Inspect author and full thread; never re-ask a
result from either search. Search the disclosure string, not a display name,
and include it in every reply.
## Classification rules
Phase 0 applies these from parent-level evidence to decide what to claim.
Phase 2 reapplies these rules after full-thread review.
Use `## Slack channels` unless the invocation narrows scope.
**Automated diagnostics are feedback.** For Slack, gate before reading.
Before claiming, use only alert/link metadata. Follow
[`automated-diagnostics.md`](references/automated-diagnostics.md) for ownership,
claim, and stop/continue; inspect logs, tests, and artifacts only afterward.
**Defects and design feedback.** A clear bug has observable broken behavior: a
click or submit does nothing, an action errors, data is lost or reverted, the
result is wrong, or a working flow regressed. A credible "nothing happens" is
valid evidence — inspect the owning path before doubting the reporter.
Do not change code for an unrelated product idea, praise, status update, merge
or review request, irrelevant bot forward, duplicate, or work outside the
invocation's ownership.
**Subjective UX proposals need human review.** Adding buttons/chrome or changing
visibility, placement, emphasis, or discoverability (including “hard to find”)
is a product proposal, not a defect. Check overflow, keyboard, Cmd+K, and
contextual surfaces first. Recap the ask, findings, options, recommendation,
and tradeoff; mark **Skipped**. A report or `:upvote:` never authorizes automatic
implementation; only a user-directed task may implement an approved approach.
If claimed, keep 👀, post **Skipped** once, and don't ask the reporter to choose.
Auto-fix objective defects only: broken behavior/results, misalignment,
overlap/clipping, illegibility, unusable focus/targets, jank, jitter,
measurable slowness, regressions. Separate defects from preferences; measure
failures with `text-heavy-ui`. Content remains Alice's unless claimed.
### `:upvote:` authorizes feature requests
An `:upvote:` from **the invoking identity** - not from anyone else - promotes
an otherwise out-of-scope item into scope and authorizes the work. Subjective
UX proposals are the exception: an upvote routes them for human review, not
implementation by this sweep.
Find them alongside the newest-message scan:
```
slack_search: hasmy::upvote: in:<#CHANNEL>
```
`hasmy:` is already scoped to the connected identity you verified, so every
hit is an endorsement by definition. Hits are not self-evidently in scope —
the query also returns ordinary replies and old polls that happen to carry the
reaction. Take the ones that name a concrete improvement; skip the rest
without comment.
An upvote endorses an otherwise out-of-scope **feature request** and skips only
the clear-bug bar; it does not change ownership, reaction, verification, or
question-budget rules. Subjective UX proposals remain review-only as above.
Build the smallest eligible endorsed version, name Sid or Alice, and state
requested versus actual behavior in the recap. Add `👀` before investigation or
delegation and read it back. Keep it evidence-limited until Phase 2's four bars
hold; then use **Shipped**, adding `✅` only if it meets **Fixed**.
Don't search `has::eyes:`; use the owner or handoff path above.
For GitHub, Sentry, and first-party Agent-Native Analytics, use native state as
the cursor: recent open or unresolved items with no maintainer disposition,
deduplicated against Slack. If a source cannot be read, record it as
**unavailable**. Never report "nothing matched" for a source you could not
query.
<!-- framework-repo-only:start -->
### CI failures
Run `pnpm ci:red-report`; follow [CI triage](references/ci-red-report.md).
Automated CI, uptime, and monitoring findings use grouped `#qa-agent-native` rollups;
read artifacts and keep occurrences here, never issue-track them.
Query failures mean **CI unavailable**, not empty. Deploy/release/publish rows
follow [`deployment-recovery.md`](references/deployment-recovery.md) and stay
active through target proof; track source-fix disposition separately.
<!-- framework-repo-only:end -->
### GitHub issues, Sentry, and Agent-Native Analytics are first-class feedback
Read each issue's body, comments, author, labels, linked PRs. Treat
prior `fixed`, `shipped`, or `merged` comments as leads; recheck the surface.
When a fix merges, record **Fixed** and link proof in the recap. Close a GitHub
issue only when this invocation explicitly authorizes it; otherwise record the
pending close. Track release/runtime gaps separately.
Before claiming an issue, check comments for handoffs. If someone offers a PR,
or Steve asks them to, mark **Owned elsewhere**; do not investigate, edit, test,
ship, reply, or close it. A direct request overrides this.
Fix root causes or ask what's blocking; triage human issues, not automated
finding mirrors covered by QA rollups. Feature requests and
subjective feedback need user/`:upvote:` authorization. Ask three questions max;
re-read before posting/closing.
Query both production Sentry projects - frontend/browser and backend/CLI -
paginate unresolved issues, and record representative events, releases, and
fingerprints. Classify each as repo-owned, external/provider,
deployment/configuration, or unclear. Fix repo-owned failures at the boundary
and verify locally. Use hosted runtime only when the full symptom cannot be
reproduced locally and hosted behavior is needed. Track release gaps separately;
don't hold a merged fix open. Record other external actions; silence or a stale
release doesn't prove the error is gone.
Query authenticated Agent-Native Analytics error issues in parallel. Use
`list-error-issues` for unresolved groups, then `get-error-issue` for stacks,
occurrences, breadcrumbs, tags, and replay links. It captures client exceptions
and server `captureError()` failures when the server Analytics key/provider is
configured. Use it as the Sentry fallback when rate-limited. Do not query
`error_issues` or `error_events` through
`query-agent-native-analytics`; use that action only for bounded event/LLM
correlation. Apply the same local-first rule. Fix worthwhile repo-owned failures
at their boundary; record external, deployment, or unclear issues without
inventing a fix.
### Chat run health
Run outcomes never reach Sentry; follow
[`chat-run-health.md`](references/chat-run-health.md).
### Deployment, release, and publish failures
Scan app/template, desktop, and package lanes every sweep, even without linked
feedback. Carry active run IDs, queued/running runs, failures, and missing/stale
artifacts across cursors. Fix repo causes; record external/manual causes with
the next owner/action. CI-red deploy rows from [CI triage](references/ci-red-report.md)
reuse this operational fingerprint. Follow
[`deployment-recovery.md`](references/deployment-recovery.md) for recovery and
target proof; keep delivery active until proof passes. A source issue may be
**Fixed** separately; delivery gaps are never **Quarantined**. Green CI or
merged source does not prove delivery.
## Phase 2: fix
Before changing code, read `fix-at-the-boundary`, `verifying-changes`, and
`concurrent-agents`. Read `ship` when a verified fix is ready to publish.
**Read the evidence the reporter already attached before forming a hypothesis.**
Open every screenshot, clip, and linked artifact. The error text in a
screenshot is usually the whole diagnosis. Track an artifact that is
permission-gated or expired separately from one that was never provided —
inaccessible is not absent.
### Attempt local reproduction before evidence-limiting
For each concrete objective defect, try the reported flow before deciding it
cannot be reproduced or fixed. Trace the screenshot, URL, visible action, and
error through the app to its route, action, provider, or form contract; use
those clues to choose the closest runnable local seam. Exercise the flow with
a local build and synthetic fixtures. If its external dependency is unavailable,
mock that boundary or submit the same shape to a local validator. Do not use a
reporter's real email or create a real external record merely to prove a
failure.
Record the route or action, build, fixture, steps, expected and actual result,
and error. Code inspection alone is not a reproduction attempt, and
**Not reproducible - attempted** requires an actual flow attempt. Ask the
reporter only when a specific missing detail would change the attempt or fix;
otherwise make the best local attempt with the evidence already available.
If the attempt stops at a concrete access or environment limit, name what was
tried and what exact behavior remains untested. Measure misses with
`feedback-no-local-repro`.
**Sweep siblings before you claim anything is fixed.** Derive the fingerprint
from the symptom, not the file — the exact crashing token, call shape, or
literal — then search the repo for it and enumerate every hit in your recap
before editing. `fix-at-the-boundary` owns the method. A fix that repairs the
reported route and leaves the identical crash in its sibling is not a fix, and
the reporter was told otherwise.
### Repeats get more time, not the same fix again
Before fixing anything, search the channel for prior reports of the same
symptom:
```
slack_search: <2-4 distinctive symptom words> in:<#CHANNEL>
sort=timestamp sort_dir=desc
```
Search in the reporter's words — `zoom invalid_client`, `logout twice` — not
your diagnosis. Read hits; one bug may have different descriptions.
**A repeat report after a Fixed claim is evidence that fix failed.** It is the
only falsification signal this workflow gets, and it outranks your belief that
the code is correct. Treat it as a stop, not a fresh report:
1. **Find what we said last time** — the prior thread, its **Fixed** reply,
and the commit behind it. You want the claim that turned out wrong.
2. **Name why it did not take**: never deployed; fixed a sibling path; root
cause misdiagnosed; or one symptom of several. Each needs a different
repair, and re-applying the same class of change is how one bug ships
three times.
3. **Reproduce end to end before editing, verify end to end after.** A passing
unit test is not sufficient for a repeat — exercise the surface the reporter
used. `verifying-changes` owns the proof.
4. **Cluster identical causes** into one investigation and fix, but keep a
recap row per source thread; Phase 3's reply rules still apply.
Record `Repeat of: <link>` and the prior failed fix in each row; never call a
repeat fixed on the evidence that supported the earlier claim.
Measure this gate with friction keys `false-done` and
`repeat-report-refix`. Run `node scripts/agent-friction-report.mjs --weeks 2
--pattern <key>` for each before changing it and again later. A climbing count
requires a mechanical proof or release gate, not more prose.
### Reproduction and verification detail
Use [`reproduction-and-verification.md`](references/reproduction-and-verification.md)
for the bug-bash contract, reproduction ledger, and regression proof.
### Npx and package reports have a release follow-up
Use [`deployment-recovery.md`](references/deployment-recovery.md) for npx
version, registry, publication, and existing-app upgrade proof. A verified merge
may be **Fixed** while its delivery row stays open; a local scaffold or beta
promise is not delivery.
### Documentation has a runnable proof obligation
View on GitHub