Skip to content

feat: weekly workflow to solve non-actionable positive reviews - #38

Draft
Bilb wants to merge 4 commits into
fix-zendesk-over-apifrom
feat-zendesk-resolve-positive-reviews-weekly
Draft

feat: weekly workflow to solve non-actionable positive reviews#38
Bilb wants to merge 4 commits into
fix-zendesk-over-apifrom
feat-zendesk-resolve-positive-reviews-weekly

Conversation

@Bilb

@Bilb Bilb commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Not started with the --apply just yet.
Probably worth not merging it before I can make sure it works correctly (gh needs the workflow to be on the main branch to run it).

Bilb added 4 commits August 7, 2026 10:19
5,253 app-store reviews sit unsolved, 4,812 of them still `new`, against
428 non-review unsolved tickets — so the backlog is 92% reviews nobody
was ever going to action. Solving them was already being done by hand:
4,959 are already solved or closed.

resolve_reviews.py searches `via:any_channel status:new`, re-checks each
ticket locally against triage.is_store_review and triage.review_stars
(the query cannot express the rating, and detection must not drift from
the triage's), and PUTs solved in batches of 100 through update_many,
polling each asynchronous job so per-ticket failures fail the run.

It writes to Zendesk, so the guards are the design: nothing happens
without --apply, a scheduled run applies but a manual dispatch is a dry
run unless asked, `new` only by default since an `open` review may have
had agent activity, `solved` never `closed`, `additional_tags` rather than
`tags` so a ticket's own tags survive, and the note is private because a
public comment would email the reviewer. Solving can fire triggers —
including satisfaction surveys to real reviewers — which the script,
workflow and README all flag, with a small first run recommended.

26 offline tests cover the guards rather than the happy path. Not run
against Zendesk yet, by request.
"Backlog: 5,680 unsolved" read as 5,680 things wanting attention when 92%
of them are AppFollow reviews and the human queue is 428. The line now
leads with the review-excluded number and keeps the review count beside
it, so the figure a reader acts on is the one that means something.

A second count-only search does it — one extra request, no fetching, the
same endpoint the existing line already uses. Both counts stay best
effort: if the new one fails the line falls back to the plain total
rather than vanishing, which a test pins.
The flag was a hedge, not a decision: I added it without knowing what an
`open` review actually is, so it offered a widening nobody had a reason to
use. Checking settles it — in a 100-ticket sample of the 441 open reviews,
every single one had an assignee, a group, and an updated_at later than
its created_at. Something has already handled those, which is exactly the
class of ticket a bulk status change should leave alone.

So `status:new` is now the query, not a default, and the reason is
recorded next to it rather than a guess about agent activity. The
workflow input and the flag plumbing go with it.
--min-stars let a dispatch lower the floor, and lowering it is exactly the
wrong move: 3★ and below are the reviews the triage reads as bug reports
in disguise, so a run at --min-stars 3 would close the ones most worth
looking at. Renamed DEFAULT_MIN_STARS to MIN_STARS since it is no longer a
default, and dropped the flag, its 1-5 validation, and the workflow input.

select_resolvable still takes the floor as an argument — it stays a pure
function the tests can drive at any threshold — but main passes the
constant and nothing else can.

Verified with a guarded dry run: 177 of 200 fetched would be solved,
GET only.
@Bilb
Bilb marked this pull request as draft August 7, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant