Problem
resolveClaimReviewerPrompt() in server/services/cosTaskGenerator.js resolves the JIRA play button's reviewers with an empty metadata object:
const config = resolveClaimReviewerConfig({}, codeReviewDefaults, codeReviewDefaults?.reviewers);
Its own docstring says it "[m]irrors the scheduled claim-work resolution so the JIRA play button honors the user's reviewer choice." It does not — {} skips the claim-work task metadata layer entirely, so the button resolves straight from the Code Review Defaults.
The result is that the same class of button resolves reviewers two different ways depending on the app's tracker: a GitHub/GitLab/PLAN.md claim (buildClaimWorkTask → claimReviewersFrom) layers claim-work metadata over the defaults, while the JIRA claim (buildJiraTicketTask → resolveClaimReviewerPrompt) uses the defaults alone. A user who pins a reviewer chain for claims gets it on three trackers and silently not on the fourth.
It also makes GET /api/apps/:id/claim-reviewers (added in #6202's follow-up) wrong for JIRA: it is named as if it answers "what will a claim run" but resolves the /do:next way, so wiring useClaimReviewers into KanbanBoard.jsx today would display a chain the JIRA run won't use.
Decision (made, not deferred)
Make the JIRA path layer the same metadata, rather than documenting the difference. The override is a claims-wide reviewer choice; a tracker is not a reason to ignore it, and the docstring already states the intended contract.
resolveClaimReviewerPrompt() takes the app and resolves through claimReviewersFrom(metadata, codeReviewDefaults) with metadata from resolveClaimWorkMetadata(app) — the same two lines resolveAppClaimReviewers already runs.
buildJiraTicketTask passes its app through.
- Then
resolveAppClaimReviewers genuinely answers for every claim, and KanbanBoard.jsx can render the same read-only "Reviewed by" summary the Issues tab does.
Rejected alternative: leave JIRA on the defaults and reword the docstring. It keeps a per-tracker rule nobody can discover from the UI, and leaves the lookup route's name a lie for one tracker.
Related, same class
triggerCosOnDemandTask('claim-work', appId) from client/src/components/apps/tabs/AutomationTab.jsx and client/src/components/cos/tabs/ScheduleTab.jsx is also a manual claim launcher with no reviewer display at all. It resolves correctly (it is the claim-work task), so this is a visibility gap, not a resolution bug — worth the same one-line summary once useClaimReviewers exists.
Acceptance
- A
claim-work reviewer override reaches a JIRA play-button claim's {reviewers} CSV, verified in cosTaskGenerator.test.js alongside the existing buildJiraTicketTask coverage.
resolveClaimReviewerPrompt's docstring matches what it does.
GET /api/apps/:id/claim-reviewers returns the same chain a JIRA claim runs for a JIRA-tracked app.
Problem
resolveClaimReviewerPrompt()inserver/services/cosTaskGenerator.jsresolves the JIRA play button's reviewers with an empty metadata object:Its own docstring says it "[m]irrors the scheduled claim-work resolution so the JIRA play button honors the user's reviewer choice." It does not —
{}skips the claim-work task metadata layer entirely, so the button resolves straight from the Code Review Defaults.The result is that the same class of button resolves reviewers two different ways depending on the app's tracker: a GitHub/GitLab/PLAN.md claim (
buildClaimWorkTask→claimReviewersFrom) layers claim-work metadata over the defaults, while the JIRA claim (buildJiraTicketTask→resolveClaimReviewerPrompt) uses the defaults alone. A user who pins a reviewer chain for claims gets it on three trackers and silently not on the fourth.It also makes
GET /api/apps/:id/claim-reviewers(added in #6202's follow-up) wrong for JIRA: it is named as if it answers "what will a claim run" but resolves the/do:nextway, so wiringuseClaimReviewersintoKanbanBoard.jsxtoday would display a chain the JIRA run won't use.Decision (made, not deferred)
Make the JIRA path layer the same metadata, rather than documenting the difference. The override is a claims-wide reviewer choice; a tracker is not a reason to ignore it, and the docstring already states the intended contract.
resolveClaimReviewerPrompt()takes the app and resolves throughclaimReviewersFrom(metadata, codeReviewDefaults)withmetadatafromresolveClaimWorkMetadata(app)— the same two linesresolveAppClaimReviewersalready runs.buildJiraTicketTaskpasses its app through.resolveAppClaimReviewersgenuinely answers for every claim, andKanbanBoard.jsxcan render the same read-only "Reviewed by" summary the Issues tab does.Rejected alternative: leave JIRA on the defaults and reword the docstring. It keeps a per-tracker rule nobody can discover from the UI, and leaves the lookup route's name a lie for one tracker.
Related, same class
triggerCosOnDemandTask('claim-work', appId)fromclient/src/components/apps/tabs/AutomationTab.jsxandclient/src/components/cos/tabs/ScheduleTab.jsxis also a manual claim launcher with no reviewer display at all. It resolves correctly (it is the claim-work task), so this is a visibility gap, not a resolution bug — worth the same one-line summary onceuseClaimReviewersexists.Acceptance
claim-workreviewer override reaches a JIRA play-button claim's{reviewers}CSV, verified incosTaskGenerator.test.jsalongside the existingbuildJiraTicketTaskcoverage.resolveClaimReviewerPrompt's docstring matches what it does.GET /api/apps/:id/claim-reviewersreturns the same chain a JIRA claim runs for a JIRA-tracked app.