feat(webhook): dispatch design-reviewer on area:design-review label #86
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!86
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "boss/82"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #82.
Summary
design-reviewernow fires on anarea:design-reviewlabel change, closing the review half of the designer flow. Previously it only ran on designer-authored PRs — and designer hands off via issue comments, not PRs, so in the common case the reviewer never fired (seen end-to-end on #62).How it works now
area:designissue →designerrunsdesign-implement(unchanged).area:design-reviewto the issue (new step 6 indesign-implement.md).issues.labeledroute matchesarea:design-review→dispatches
design-reviewerrunning thereviewskill(
design-review.md).removes
area:design-reviewso the label state reflects that thereview has been posted.
Implementation
src/webhook-routing.ts: replaced the agent-onlyLABEL_TO_AGENTmap with aLabelRoute({ agent, baseSkill }) map.area:design→(designer, implement),area:design-review→(design-reviewer, review).agentForLabelsrenamed torouteForLabels.src/webhook-handlers.ts:handleIssueLabelednow uses the base skill from the route. Shared dispatcher renameddispatchIssueForAgentand takes abaseSkillparameter. Both{{issue_number}}and{{pr_number}}interpolate to the issue number so review-style templates keep working when dispatched from an issue label.skills/design-implement.md: step 6 attachesarea:design-reviewviamcp__forgejo__add_issue_labelsafter the handoff comment; success gated on label presence.skills/design-review.md: intro rewritten to be issue-scoped (not PR-scoped); step 5 clearsarea:design-reviewviamcp__forgejo__remove_issue_labels; success gated on label removal.routeForLabelscovers the newarea:design-review → (design-reviewer, review)mapping.handleIssueLabeledcovers both the "matched route but agent unconfigured" and "newly-added-only" rules forarea:design-review.README.mdandCLAUDE.mddescribe the label pair.Setup note (out of the PR)
The
area:design-reviewlabel itself must exist on each repo that runs this flow. Create it in the Forgejo UI (e.g.#be185d— same pink family asarea:designso they group visually). The designer skill deliberately does not auto-create the label — it surfaces a clear error iflist_repo_labelsdoesn't resolve it, so the missing-setup case is loud rather than silent.Test plan
bun x tsc --noEmit— cleanbun x biome check src/— cleanbun x biome format src/— cleanbun test— 247 pass, 0 failarea:design-reviewon the repo, then add it to #62 manually.design-reviewerpicks it up, posts a defect comment, and removes the label.Review: APPROVED
CI ✅ — run #1599, success, 2m41s on
207405e.Acceptance criteria (issue #82)
area:design-reviewlabel inlabels/schemewebhook-routing.tsmapsarea:design-review→design-reviewerLABEL_TO_ROUTEdesign-reviewerskill starts from issue handoff comment, not a PRdesign-review.mdrewrittendesign-implement.mdattachesarea:design-reviewafter handoff commentdesign-review.mdremovesarea:design-reviewon completionwebhook-routing.test.tsassertsarea:design-review→design-reviewerwebhook-handlers.test.tsasserts newly-added-only rule for the new labelOn the
labels/scheme AC: The issue asked for a schema file entry; the PR consciously omits it and explains why (setup concern, skill errors loudly on missing label rather than silently skipping). That trade-off is sound — a loud failure at first use beats a silent one — but whoever sets up a new repo needs to know. The "Setup note" in the PR body covers it. No blocking issue.Code quality
LABEL_TO_AGENT: Record<string, string>→LABEL_TO_ROUTE: Record<string, LabelRoute>with the exportedLabelRouteinterface is the right structural move: it makes the (agent, skill) pair explicit rather than encoding it implicitly through a second lookup.dispatchImplementForIssue→dispatchIssueForAgent(…, baseSkill)is a clean generalization; the caller decides the skill, the dispatcher knows only how to build a task from it.{{issue_number}}and{{pr_number}}withissue.numberin the interpolation map is correct: review-style templates that still carry{{pr_number}}don't need to be rewritten, and the values are identical so there's no confusion.area:designregression guard.design-review.mdstep 5 (remove label) is gated in the success criterion ("do not report success until …area:design-reviewhas been removed"), which closes the loop correctly.Nothing to fix. Good work.
area:designwhen addingarea:design-review#96