feat: Jira hygiene workflows#109
Conversation
Add comprehensive workflow for maintaining Jira project hygiene through automated detection, intelligent suggestions, and safe bulk operations. Features: - Link orphaned stories to epics using semantic matching (50% threshold) - Link orphaned epics to initiatives across projects - Generate weekly activity summaries for epics/initiatives - Close stale tickets with priority-based thresholds (High: 1w, Medium: 2w, Low: 1m) - Suggest triage outcomes for untriaged items based on similar tickets - Identify blocking tickets with closed dependencies - Find in-progress tickets without assignee - Suggest Activity Type values using keyword analysis - Show all blocking tickets in project All bulk operations use review-then-execute pattern for safety with comprehensive audit logging. Supports dry-run mode for testing. Commands: - /hygiene.setup - Initial configuration and validation - /hygiene.link-epics - Link orphaned stories to epics - /hygiene.link-initiatives - Link orphaned epics to initiatives - /hygiene.activity-summary - Generate weekly summaries - /hygiene.show-blocking - Show blocking tickets - /hygiene.close-stale - Close stale tickets by priority - /hygiene.triage-new - Suggest triage for untriaged items - /hygiene.blocking-closed - Find blocking-closed mismatches - /hygiene.unassigned-progress - Show in-progress unassigned - /hygiene.activity-type - Suggest Activity Type values Integration: Direct Jira REST API v3 calls via curl + jq Artifacts: Written to artifacts/jira-hygiene/ Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove suggestion to query for accessible projects in /hygiene.setup. User should provide exact project keys they want to use. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Update all command files to generate clickable links in reports: - Ticket links: [KEY](JIRA_URL/browse/KEY) - JQL search links: [View in Jira](JIRA_URL/issues/?jql=...) - URL-encoded JQL queries for proper link formatting Updated commands: - /hygiene.show-blocking - links in table and report - /hygiene.unassigned-progress - links in table and recommendations - /hygiene.blocking-closed - links to tickets and blocked items - /hygiene.link-epics - links in suggestions display - /hygiene.link-initiatives - links in suggestions display - /hygiene.close-stale - links in priority groups - /hygiene.triage-new - links in confidence-based display - /hygiene.activity-type - links in suggestions Makes reports more actionable by allowing direct navigation to tickets and searches from generated markdown files. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Change /hygiene.show-blocking to find tickets that block other work via 'Blocks' issue links, not tickets with 'Blocker' priority. Changes: - Query using issueFunction to find tickets with outward 'blocks' links - Display what tickets are being blocked in report table - Add fallback approach for Jira instances without issueFunction - Update JQL pattern in systemPrompt - Show blocked ticket links in summary and recommendations This correctly identifies tickets that are actually blocking other work, rather than just having high priority. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Enhance /hygiene.activity-summary to recursively gather details from linked Pull Requests and Merge Requests when generating summaries. Features: - Fetch PR/MR data from Jira development panel API - Support GitHub, GitLab, and Bitbucket integrations - Filter PR/MRs by update date (past 7 days only) - Include merged PRs, in-review PRs, and commit counts - Fallback to parsing PR/MR URLs from comments - Optional direct GitHub/GitLab API access via tokens Summary now includes: - Number of PRs merged vs in review - PR titles for context - Overall commit volume - Business-friendly language (avoids technical details) Optional environment variables: - GITHUB_TOKEN - For direct GitHub API access - GITLAB_TOKEN - For direct GitLab API access This provides stakeholders with concrete evidence of development progress beyond just Jira status changes. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add /hygiene.report command that generates comprehensive dashboard combining all hygiene checks into a single report. Features: - Runs all hygiene checks (read-only, no modifications) - Calculates health score (0-100) based on issue counts - Provides executive summary with issue breakdown - Lists top issues in each category with Jira links - Recommends which commands to run next - Supports custom output path and HTML format Health Score Ratings: - 90-100: Excellent 🟢 - 70-89: Good 🟡 - 50-69: Needs Attention 🟠 - 0-49: Critical 🔴 Categories Included: - Orphaned stories and epics - Blocking tickets - Stale tickets (by priority with thresholds) - Untriaged items - Blocking-closed mismatches - In-progress unassigned tickets - Missing activity types Scoring deducts points based on issue type severity: - Blocking tickets: -2 points each - Orphaned epics: -1 point each - Stale High priority: -1 point each - In-progress unassigned: -1 point each - And more... Use cases: - Weekly hygiene check - Stakeholder reporting - Project health dashboard - Identifying where to focus cleanup efforts Arguments: - --output <path>: Custom report location - --format <md|html>: Output format This command now brings the total to 11 specialized commands for comprehensive Jira hygiene management. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add base_jql field to config for customizable query filtering - Implement pagination across all 10 commands to fetch complete result sets - Update systemPrompt with pagination rules and base_jql guidelines - Add pagination examples to all command files (simple, nested, and complex) - Handle special cases: issue functions, child queries, cross-project searches - Update CLAUDE.md with pagination and base_jql documentation Fixes data loss issue where only first 50 results were returned. Users can now scope workflows to teams/labels and handle large datasets. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 0 minutes and 34 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
WalkthroughThis PR introduces a complete Jira Hygiene workflow system consisting of setup initialization, 11 specialized command workflows (linking, reporting, bulk operations, and data-quality checks), comprehensive documentation, and configuration management for automated Jira project maintenance. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@workflows/jira-hygiene/.claude/commands/hygiene.activity-summary.md`:
- Around line 122-131: Add a --dry-run flag to the bulk-post command that
currently POSTs to /rest/api/3/issue/{epicKey}/comment (the flow that prompts
"Post these summaries as comments? (yes/no)" and enforces a 0.5s rate limit);
when --dry-run is set, perform steps 1–4 (Query, Analyze, Save, Display) but
skip showing the confirmation prompt and do not execute any POST requests or
rate-limited waits—ensure the flag is wired into the command's argument parsing,
checked in the posting routine, and that the POST path (the code that builds and
sends {"body":"Weekly Activity Summary..."}) is guarded so no network calls
occur in dry-run mode.
- Around line 54-59: The current child-fetch JQL ("parent = {EPIC_KEY}") only
works for epics and misses initiative→epic→child traversal; update the logic
that builds child-fetch queries (the "Fetch child issues WITH PAGINATION" step
and the JQL using "parent = {EPIC_KEY}") to branch on issue type: if the issue
is an Initiative, first fetch its child Epics via "parent = {INITIATIVE_KEY}"
(with pagination), then for each Epic fetch its child issues via "parent =
{EPIC_KEY}" (also paginated); otherwise (for Epics) continue to use the existing
"parent = {EPIC_KEY}" flow. Ensure pagination is applied to both the
initiative→epics and epic→children fetches.
- Around line 29-31: The summary-generator currently may include closed/resolved
parent issues because user JQL or provided keys aren't forced to exclude
resolved tickets; update the "Fetch selected epics/initiatives WITH PAGINATION"
step and the logic that prepares the comment POST to enforce only unresolved
scope by either (1) appending "AND resolution = Unresolved" to any JQL used to
fetch parent epics/initiatives or (2) filtering the fetched parent issue list
before building POST bodies so only issues with fields.resolution == null (or
resolution = Unresolved) are included; apply the same unresolved-only check
where comment POSTs are created (the block referenced around the comment POST
logic) so closed tickets are never modified or commented on.
In `@workflows/jira-hygiene/.claude/commands/hygiene.activity-type.md`:
- Around line 102-110: Update the confirmation flow so bulk updates are executed
in explicit batches of at most 50 tickets: when not in --dry-run, chunk the
collection of approved tickets into groups of up to 50, and for each chunk
prompt the user with a clear confirmation (e.g. "Apply Activity Type suggestions
for N tickets? (yes/no/high-confidence-only)") and proceed with the PUT
`/rest/api/3/issue/{key}` updates for that chunk only if the user types the
exact "yes" response; otherwise skip or honor the "high-confidence-only" option.
Preserve existing behavior for --dry-run (display "DRY RUN - No changes made")
and keep the 0.5s rate limit between ticket updates.
- Around line 21-27: The JQL query uses the wrong placeholder
({ACTIVITY_TYPE_FIELD_NAME}); change it to {ACTIVITY_TYPE_FIELD_ID} so it
matches the configured key activity_type_field_id and the rest of the flow (e.g.
the update payload that uses {FIELD_ID}). Locate the JQL snippet that builds
({base_jql}) AND "{ACTIVITY_TYPE_FIELD_NAME}" is EMPTY and replace the
placeholder with {ACTIVITY_TYPE_FIELD_ID} to keep naming consistent across the
codebase.
In `@workflows/jira-hygiene/.claude/commands/hygiene.close-stale.md`:
- Around line 90-94: Update the confirmation flow under "Ask for confirmation"
to require explicit per-batch approvals limited to 50 tickets: when not
`--dry-run`, split the set of tickets (or each priority group when "by-priority"
is chosen) into batches of up to 50, prompt the user for each batch with a clear
message that requires the literal response "yes" to proceed (deny any other
response), and skip making changes until all batches have received explicit
"yes" approval; ensure the UI text shows "DRY RUN - No changes made" remains for
`--dry-run`.
- Around line 99-100: Update the HTTP method for the Jira transitions endpoint
from PUT to POST in the text that currently reads "- POST
`/rest/api/3/issue/{key}/comment` then PUT
`/rest/api/3/issue/{key}/transitions`"; change "PUT
`/rest/api/3/issue/{key}/transitions`" to use POST so the line correctly
documents the `/rest/api/3/issue/{key}/transitions` endpoint as a POST request.
In `@workflows/jira-hygiene/.claude/commands/hygiene.link-epics.md`:
- Around line 7-12: The bulk linking flow for the hygiene.link-epics command is
missing a --dry-run mode; add a --dry-run CLI flag to the hygiene.link-epics
command and thread it through the flow so when set it runs only steps 1–4
(Query, Analyze, Save, Display), skips interactive confirmation and any API
mutation calls (mass link operations), but still writes artifacts and prints
results; ensure the flag is checked in the controller/handler that performs the
mass updates (the code block referenced around lines 110–121) and used to
short-circuit mutation functions while keeping all read/analysis/save/display
logic intact.
- Around line 116-121: Before performing the PUT /rest/api/3/issue/{storyKey} to
set the "Epic Link", fetch the latest issue state and re-check the Epic Link
field to avoid TOCTOU overwrites; if the Epic Link is no longer empty, skip the
update and log the current link (apply this check inside the "Execute linking
operations" flow where you handle approved linking suggestions and before the
"Set Epic Link" update), respect the existing 0.5s rate limit, and ensure
"create epic" suggestions remain only logged and not executed.
In `@workflows/jira-hygiene/.claude/commands/hygiene.link-initiatives.md`:
- Around line 7-12: The bulk linking command /hygiene.link-initiatives currently
performs multi-issue updates without a dry-run option; add support for a
--dry-run flag in the command handler (the logic that executes the Query,
Analyze, Save, Display, Confirm, and API update steps) so that when --dry-run is
provided the handler runs only steps 1-4 (Query, Analyze, Save, Display), skips
any interactive confirmation and does not perform API modifications, and ensure
the same --dry-run behavior is implemented for the other bulk block referenced
in this file (the second bulk link block around the same command logic).
- Around line 114-118: Before issuing the PUT to /rest/api/3/issue/{epicKey} for
each approved linking, perform a pre-update GET of the epic and verify the
Parent Link field is still empty (i.e., no existing initiative link); if the
Parent Link is already set, skip the PUT to avoid stale-write/duplicate-link
conflicts. Implement this check in the linking routine (the code that iterates
approved linkings / "Execute linking operations") so the flow becomes: GET epic,
if Parent Link empty then PUT to set Parent Link to the initiative key, else
log/skip; preserve the 0.5s rate limit between requests.
In `@workflows/jira-hygiene/.claude/commands/hygiene.report.md`:
- Around line 46-97: The JQL uses the display name "Activity Type" instead of
the configured custom field ID; update the query string that currently contains
({base_jql}) AND "Activity Type" is EMPTY to reference the configured
activity_type_field_id (e.g. ({base_jql}) AND
customfield_{activity_type_field_id} is EMPTY) using the same substitution
mechanism used elsewhere in the file so the query uses the instance-specific
custom field ID from config rather than the hardcoded display name.
In `@workflows/jira-hygiene/.claude/commands/hygiene.triage-new.md`:
- Around line 119-123: Update the confirmation step for bulk triage so it
enforces an explicit "yes" confirmation and caps applied tickets to 50 per
confirmation batch: when --dry-run is set, still skip applying and display "DRY
RUN - No changes made"; otherwise prompt exactly "Apply triage suggestions?
(yes/no/high-confidence-only)" but only proceed on the literal response "yes"
and only apply up to 50 tickets from the current selection (reject or require
re-confirmation if >50); preserve the existing "high-confidence-only" behavior
(apply only items with ≥5 similar items) and ensure the code path that performs
the changes respects the 50-item cap before executing.
- Around line 23-26: The query currently uses issue creation date ({base_jql}
AND status = New AND created < -{DAYS}d) which misclassifies issues that were
recently moved back to New; replace the created predicate with a status-change
predicate so triage age uses time-in-status, e.g. use "{base_jql} AND status =
New AND status changed TO New BEFORE -{DAYS}d" (or the equivalent "status
changed TO New < -{DAYS}d" variant supported by our JQL engine) so only issues
that have been continuously New for >N days are returned.
In `@workflows/jira-hygiene/.claude/commands/hygiene.unassigned-progress.md`:
- Around line 17-20: The JQL snippet `({base_jql}) AND status = "In Progress"
AND assignee is EMPTY` hardcodes a status name and will miss projects that use
different status labels; update that query to use the status category instead
(e.g., replace the `status = "In Progress"` predicate with `statusCategory = "In
Progress"`) so the block shown in the doc (the JQL code snippet) matches all
in-progress statuses across projects.
In `@workflows/jira-hygiene/CLAUDE.md`:
- Around line 195-201: Update the checklist item that currently reads "All 10
command files exist in .claude/commands/" to reflect the correct count of
specialized commands (change 10 to 11) and ensure consistency with
ambient.json's command list (setup, link-epics, link-initiatives, report,
activity-summary, show-blocking, close-stale, triage-new, blocking-closed,
unassigned-progress, activity-type); modify the text in the checklist so it
accurately states "All 11 command files exist in .claude/commands/" (or similar
phrasing) and run a quick scan of the README.md and ambient.json references to
confirm all docs now match.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 19908f26-4f92-4144-b382-a2388a94a2f7
📒 Files selected for processing (14)
workflows/jira-hygiene/.ambient/ambient.jsonworkflows/jira-hygiene/.claude/commands/hygiene.activity-summary.mdworkflows/jira-hygiene/.claude/commands/hygiene.activity-type.mdworkflows/jira-hygiene/.claude/commands/hygiene.blocking-closed.mdworkflows/jira-hygiene/.claude/commands/hygiene.close-stale.mdworkflows/jira-hygiene/.claude/commands/hygiene.link-epics.mdworkflows/jira-hygiene/.claude/commands/hygiene.link-initiatives.mdworkflows/jira-hygiene/.claude/commands/hygiene.report.mdworkflows/jira-hygiene/.claude/commands/hygiene.setup.mdworkflows/jira-hygiene/.claude/commands/hygiene.show-blocking.mdworkflows/jira-hygiene/.claude/commands/hygiene.triage-new.mdworkflows/jira-hygiene/.claude/commands/hygiene.unassigned-progress.mdworkflows/jira-hygiene/CLAUDE.mdworkflows/jira-hygiene/README.md
Implement all 16 actionable review comments:
1. Add --dry-run flag support:
- hygiene.activity-summary: skip confirmation and POST requests
- hygiene.link-epics: skip confirmation and API mutations
- hygiene.link-initiatives: skip confirmation and modifications
2. Fix initiative→epic→child traversal:
- Check issue type in activity-summary
- Fetch child Epics first for Initiatives, then their children
- Apply pagination at both levels
3. Enforce unresolved-only scope:
- Append 'AND resolution = Unresolved' to JQL in activity-summary
- Filter fetched issues to exclude resolved tickets
4. Add 50-ticket batch confirmations:
- hygiene.activity-type: batch updates, require exact 'yes'
- hygiene.close-stale: batch by priority groups, max 50
- hygiene.triage-new: batch mode with explicit confirmation
5. Fix JQL field references:
- hygiene.activity-type: use {ACTIVITY_TYPE_FIELD_ID} not FIELD_NAME
- hygiene.report: use activity_type_field_id from config
- hygiene.triage-new: use status-change predicate not created date
- hygiene.unassigned-progress: use statusCategory not hardcoded status
6. Add TOCTOU checks before bulk updates:
- hygiene.link-epics: GET to verify Epic Link still empty
- hygiene.link-initiatives: GET to verify Parent Link still empty
7. Fix HTTP method:
- hygiene.close-stale: use POST for transitions endpoint not PUT
8. Update documentation:
- CLAUDE.md: change 10 to 11 command files
All changes preserve existing behavior while adding safety and correctness
improvements as requested by the reviewer.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
I ran this, and provided feedback on slack which has been folded into this branch. This PR makes sense because it has the hygiene.setup command which makes it generic enough for any user. |
Closes #102
This workflow includes some reporting, linking via semantic analysis or Jira items provided as a project or a JQL.
The user has the option to receive a dry run of all the workflows or allow for more autonomy in making bulk changes.