AI Prompts

A library of useful prompts for Duo and other AI tools used by our team

Support Rotation Handover Prompt

Here is a prompt than can be used in Duo Agentic mode to summarise the work on an issue which has not yet been closed, in order to hand it over to another engineer. Execute this prompt and you can copy the response into the handover notes when another colleague begins their support rotation:

Prompt text
Please concisely summarize the current status of this issue, in order to hand it
over to the next backend engineer on customer support rotation duty for the
Groups & Projects team.

Use this template:

---

A handover comment generated by Duo and reviewed by me:

### Current status

<!-- Content of current status -->

*Confidence: <!-- Percentage confidence level in the accuracy of this status -->*

### Action items

- <!-- GitLab handle of DRI --> (*Confidence: <!-- Percentage confidence in who should be DRI for this item -->*): <!-- Action item -->. (*Confidence: <!-- Percentage confidence in the validity of this action item -->*)

---

- Be sure, or be conservative.
- When making assertions, be wary of hallucinations.
- Use qualifying language as appropriate.
- If you reference a resource with a URL, such as a GitLab issue or Zendesk
  ticket number, then make it a link.
- Read linked URLs if the added context might improve your answer.
- Answer with only Markdown code. I will review it and post it.
Example output

A handover comment generated by Duo and reviewed by me:

Current status

This is a regression in GitLab 18.3 where the last_repository_check_failed URL parameter filter is not working in the admin projects page. The issue was identified as being caused by the admin_projects_vue feature flag migration - when the flag is enabled, the parameter is ignored and all projects are returned instead of filtering for projects with failed repository checks.

@smaglangit has taken ownership of this issue and is actively working on a fix. The issue is currently in workflow::in dev status and has been linked to #561340 (the feature flag cleanup issue) as a blocking dependency. Multiple merge requests have been referenced (!203618, !203621, !204306) indicating active development work.

The issue affects customers on GitLab 18.3.1 and has been reproduced on v18.3. It’s scheduled for the 18.4 milestone (release date: September 18, 2025) with only 2 days remaining until code cutoff.

Confidence: 95%

Action items

  • @smaglangit (Confidence: 100%): Complete the fix for the last_repository_check_failed filter regression as part of the admin_projects_vue feature flag migration work. (Confidence: 95%)
  • @smaglangit (Confidence: 90%): Ensure the fix is included in the 18.4 milestone given the tight timeline (code cutoff in 2 days). (Confidence: 85%)

Request For Support Issue Triage

This prompt can help summarise what could be causing an issue and find good starter questions to ask a customer before further development can happen:

Prompt text
Investigate this issue, read the feature docs, suggest possible root causes and
questions to ask the customer.

Identify if any other issues in the `request-for-help` project could be related.
Example output

Epic Summary Prompt

This prompt can be used to ask Duo to look at an individual epic and summarise the most recent changes and blockers in the last week. Use it to formulate a weekly status update message which is readable and easy to dig into for links.

Prompt text
Generate a status update for this Epic using the following format.
The "Achievements" section should highlight any issues closed within the last 7
days since the last status update, with a short (1-2 sentence) summary of what
the issue accomplishes for customers. "Blockers" can be either left empty,
or use any issues whose status is blocked. For the "Next" section, include any
issues that have an assignee and have the status "in dev" or "in review".

---

## <!-- Date in YYYY-MM-DD --> – <!-- Title of Epic -->

<!-- Create a high level summary -->

### :tada: **Achievements**:

- <!-- Content of Achievements -->

### :issue-blocked: **Blockers**:

- <!-- Content of Blockers (optional) -->

### :arrow_forward: **Next**:

- <!-- Content of Next -->

---

- Be sure, or be conservative.
- When making assertions, be wary of hallucinations.
- Use qualifying language as appropriate.
- If you reference a resource with a URL, such as a GitLab issue or Zendesk
  ticket number, then make it a link.
- Read linked URLs if the added context might improve your answer.
- Answer with only Markdown code. I will review it and post it.
- Format the summary in a conversational, readable manner. Avoid business speak.
- You should use markdown for the output and wrap it in backticks.
Example output

2025-09-10 – Organization backend essentials

The team continues working on the final cleanup tasks to complete the Organization backend essentials. All remaining issues are actively being developed and are targeted for the 18.4 milestone.

🎉 Achievements

  • No issues were completed since the last status update on 2025-09-08

:issue-blocked: Blockers

  • N/A

▶️ Next

Review Assigned MRs

Automatically review all open MRs assigned to you for review where you have not yet commented or approved. For each matching MR it follows the “MR Review” prompt below to generate and post draft review comments.

Prompt text
# Review Assigned MRs

Automatically review all open MRs assigned to you for review where you haven't yet commented or approved.

Use CLI `glab` to interact with GitLab from the command line.

## Workflow

1. **Fetch open MRs assigned for review** where you haven't interacted
2. **For each MR**, follow the "MR Review" prompt to generate and post draft review comments

## Step 1: Get MRs Needing Review

```bash
glab mr list --reviewer=@me --repo gitlab-org/gitlab --per-page 50 --output json > /tmp/mrs.json

jq -r '.[] | select(.state == "opened") | "\(.iid)|\(.title)"' /tmp/mrs.json | while IFS='|' read -r iid title; do
  # Check if I've approved
  approved=$(glab api "projects/278964/merge_requests/$iid/approvals" 2>/dev/null | jq '[.approved_by[]?.user.username] | map(select(. == "aakriti.gupta")) | length')

  # Check if I've commented
  commented=$(glab api "projects/278964/merge_requests/$iid/notes?per_page=100" 2>/dev/null | jq '[.[]? | select(.author.username == "aakriti.gupta")] | length')

  if [ "$approved" = "0" ] && [ "$commented" = "0" ]; then
    echo "$iid | $title"
  fi
done
```

This returns MRs in the format:
```
232454 | Resolve "Bug: .well-known/oauth-protected-resource returns resource as an array"
231929 | Fix missing test coverage for SyncFindingEnrichmentWorker
```

## Step 2: Review Each MR

For each MR returned in Step 1, follow the "MR Review" prompt to:

1. Fetch the MR diff: `glab mr diff <MR_IID>`
2. Fetch the MR description: `glab mr view <MR_IID>`
3. Generate review comments using Conventional Comments format
4. Post draft notes to the MR diff lines using the GitLab API

Refer to the "MR Review" prompt for detailed instructions on:
- Comment format (Conventional Comments)
- How to post draft notes to specific diff lines
- Review guidelines for different file types

## Step 3: Summary

After reviewing all MRs, provide a summary:

```
Reviewed X MRs:

1. MR !232454 - Posted Y draft comments
2. MR !231929 - Posted Z draft comments
...

Visit each MR to review and submit the draft comments.
```

## Notes

- Replace `aakriti.gupta` with the current user's GitLab username
- Replace `278964` with the appropriate project ID (gitlab-org/gitlab = 278964)
- Draft comments are only visible to you until submitted
- Review each MR's draft comments before submitting to ensure accuracy

MR Review

Review a single GitLab merge request as a staff-level maintainer using the Conventional Comments format, then post the findings as draft notes on the relevant diff lines. Covers Ruby quality checks, database migrations, test coverage, and security guidance.

Prompt text
# GitLab Code Review Ruleset

You are a staff-level GitLab maintainer. Review merge requests using **Conventional Comments** format.

Use CLI `glab` to interact with GitLab from the command line.

## Comment Format

Use the Conventional Comments format for all review comments:

```
**<label> [decorations]:** <subject>

[discussion]
```

- **label**: The type of comment (see Labels below)
- **subject**: The main message of the comment
- **decorations** (optional): Extra context in parentheses, comma-separated (e.g., `non-blocking`, `blocking`, `if-minor`)
- **discussion** (optional): Supporting statements, context, reasoning, and next steps

### Labels

| Label | Description |
|-------|-------------|
| `praise:` | Highlights something positive. Leave at least one per review. |
| `nitpick:` | Trivial preference-based requests. Non-blocking by nature. |
| `suggestion:` | Proposes improvements. Be explicit on *what* and *why*. |
| `issue:` | Highlights specific problems. Pair with a suggestion when possible. |
| `question:` | Asks for clarification when unsure if something is a problem. |
| `thought:` | An idea that popped up. Non-blocking, but valuable for mentoring. |
| `chore:` | Simple tasks that must be done before acceptance. |
| `todo:` | Small, trivial, but necessary changes. |
| `typo:` | Misspelling issues. |
| `note:` | Non-blocking highlights for the reader to take note of. |

### Decorations

- `(non-blocking)` - Should not prevent acceptance
- `(blocking)` - Must be resolved before acceptance
- `(if-minor)` - Resolve only if changes are trivial

### Examples

```
**suggestion (non-blocking):** Consider using `preload` instead of `includes` here.

This would avoid the N+1 query when accessing the association in the view.
```

```
**issue (blocking):** This endpoint lacks authorization checks.

All new endpoints must verify permissions. See https://docs.gitlab.com/development/permissions/
```

```
**praise:** Excellent test coverage for edge cases!
```

## How to Fetch MR Context

- **Using glab**: `glab mr view <MR_IID>` or `glab mr diff <MR_IID>`
- **Diff URL**: append `/diffs.diff` to the MR URL
- **Quote sources**: cite guideline URLs when drawing conclusions

## File-Specific Review Instructions

### General Standards (all files)

1. Ensure inclusive language (e.g., prefer `allowlist` over `whitelist`)
2. Verify CE/EE code separation:
   - Code in CE should not directly reference EE modules
   - EE extensions should use `prepend_mod` pattern

### Ruby Code Quality (`**/*.rb` excluding `spec/**/*`)

1. Check for N+1 queries - ensure use of `includes()`, `preload()`, or `eager_load()`
2. Ensure `update_all`, `delete_all`, `destroy_all` have proper conditions
3. Ensure authorization checks in controller actions and API endpoints
4. Ensure all modified queries are flagged as needing a database reviewer
5. For ActiveRecord callbacks, verify they only modify the current model

### Database Migrations

1. Ensure migrations are reversible
2. Ensure bulk operations use batched migrations
3. Use post-migrations for time-consuming operations
4. Ask: "Have you triggered the db:gitlabcom-database-testing pipeline?"

### Test Coverage

1. Use shared examples to reduce duplication
2. For conditional logic, verify each branch has test coverage
3. Flag missing edge case coverage
4. Follow the testing pyramid: most tests at unit level

## Database

- **Query plans required**: all new/modified queries must include `EXPLAIN (ANALYZE, BUFFERS)` plans
- **Column removal — 3-release process**: (N) `ignore_column`; (N+1) deploy; (N+2) drop column

## Security

- **SSRF**: outbound requests with user-supplied URLs must use `Gitlab::HTTP`
- **XSS**: never use `html_safe`/`raw` on user input
- **SQL injection**: all dynamic SQL must be parameterized

## Posting Draft Review Comments

After generating the review, post each comment as a draft note on the specific diff line using the GitLab API. Draft notes are only visible to you until you submit the review.

### Step 1: Get MR diff metadata

```bash
glab api "projects/<PROJECT_ID>/merge_requests/<MR_IID>/versions" | jq '.[0]'
```

Extract from the response:
- `head_commit_sha` → use as `head_sha`
- `base_commit_sha` → use as `base_sha`
- `start_commit_sha` → use as `start_sha`

### Step 2: Post draft notes for each comment

For each review comment, create a draft note on the specific line using JSON input:

```bash
glab api --method POST "projects/<PROJECT_ID>/merge_requests/<MR_IID>/draft_notes" \
  --header "Content-Type: application/json" \
  --input - << 'EOF'
{
  "note": "**<label> [decorations]:** <subject>\n\n<discussion>",
  "position": {
    "base_sha": "<base_sha>",
    "head_sha": "<head_sha>",
    "start_sha": "<start_sha>",
    "old_path": "<file_path>",
    "new_path": "<file_path>",
    "new_line": <line_number>,
    "position_type": "text"
  }
}
EOF
```

**Parameters:**
- `note`: The comment text in Conventional Comments format
- `position[base_sha]`: Base commit SHA from diff versions
- `position[head_sha]`: Head commit SHA from diff versions
- `position[start_sha]`: Start commit SHA from diff versions
- `position[old_path]`: File path (same as new_path for modified files)
- `position[new_path]`: File path (e.g., `app/models/user.rb`)
- `position[new_line]`: Line number in the new version of the file
- `position[position_type]`: Use `text` for line comments

**Example:**

```bash
glab api --method POST "projects/278964/merge_requests/228021/draft_notes" \
  --header "Content-Type: application/json" \
  --input - << 'EOF'
{
  "note": "**suggestion (non-blocking):** Consider using `preload` instead of `includes` here.\n\nThis would avoid the N+1 query when accessing the association in the view.",
  "position": {
    "base_sha": "cc80b13308eefac69bae498108c49a5f603357c8",
    "head_sha": "19e7cdffaf7f50da1c80e880b34a6a6812bd8aa0",
    "start_sha": "5f8d49772a3efa99aa2cf3c601367ab9e5f4d01f",
    "old_path": "app/models/user.rb",
    "new_path": "app/models/user.rb",
    "new_line": 45,
    "position_type": "text"
  }
}
EOF
```

### Step 3: Notify user to submit review

After posting all draft notes, remind the user:

> Draft review comments have been posted. Visit the MR to review and submit:
> https://gitlab.com/gitlab-org/gitlab/-/merge_requests/<MR_IID>

## Project IDs

- `gitlab-org/gitlab`: 278964
- Use `glab api "projects/:fullpath"` to get project ID for other projects

## Review Output Format

1. **Summary**: 2-3 sentence overview
2. **Findings**: List each comment with file, line, and the conventional comment
3. **Post as drafts**: Use the steps above to post each comment to the MR

Weekly Epic Update

Generate a comprehensive weekly status update for a GitLab epic by crawling all related activity across child issues, MRs, and sub-epics, then synthesizing it into key themes, blockers, and next steps.

Prompt text
# Epic Weekly Status Update

Generate a comprehensive weekly status update for a GitLab epic by crawling all related activity.

## Input

The user provides:
- A GitLab epic URL (e.g. `https://gitlab.com/groups/gitlab-org/-/work_items/17954`)
- Optionally, a number of days to look back (default: 7)
- Optionally, additional context from co-workers (hours spent, blockers, ad-hoc updates)

## Step 1: Crawl the Epic Hierarchy

1. Fetch the epic via GraphQL using `glab api graphql` with the `group(fullPath) > workItem(iid)` query
2. Get all direct children using the `WorkItemWidgetHierarchy` widget (children with `iid`, `title`, `state`, `updatedAt`, `createdAt`, `closedAt`, `webUrl`, `workItemType`)
3. For each child that is an **Epic**, recursively fetch its children the same way
4. Continue until all levels of the hierarchy are resolved

## Step 2: Filter to Recent Activity

From the full hierarchy, identify all items where ANY of the following occurred within the lookback window:
- `updatedAt` is within the window
- `createdAt` is within the window
- `closedAt` is within the window

## Step 3: Fetch MRs for Each Active Item

For each recently-active **Issue** (not epics), fetch related merge requests using the REST API:
```
glab api "projects/<project_path_encoded>/issues/<iid>/related_merge_requests"
```

Collect all MRs and note their state (`merged`, `opened`, `closed`), `merged_at`, `updated_at`, and `title`.

## Step 4: Fetch MR Details

For each MR that was updated/merged/opened within the lookback window, fetch its details via REST API:
```
glab api "projects/<project_path_encoded>/merge_requests/<iid>"
```

Extract the `description` (first 500 chars), `author`, `state`, `created_at`, `updated_at`, `merged_at`.

## Step 5: Synthesize Into Key Themes

Do NOT just list individual issues and MRs. Instead, group the work into **3-5 key themes** that tell a narrative about what the team accomplished. Each theme should:
- Have a short bold title summarizing the area of work
- Explain the significance of what was done (not just what, but why it matters)
- Link to the relevant MRs and issues inline
- Be written in past tense for completed work, present tense for in-progress work

## Step 6: Identify Blockers

Look for:
- MRs that are sequentially dependent (one must merge before another can proceed)
- Issues that have been open and updated but have no MR yet
- Any items the user explicitly flagged as blocked

## Step 7: Determine Next Steps

Based on open MRs in review, open issues with recent activity, and newly created issues/epics, determine what comes next. Be specific with links.

## Step 8: Estimate Hours

- Use the previous week's status update (if available in the epic description) as a baseline
- Factor in: number of MRs merged, MRs in review, new issues/epics created, research/planning work
- Incorporate any hours explicitly provided by the user or co-workers
- Round to the nearest 5h

## Output Format

Produce the status update in exactly this format:

```
## Status YYYY-MM-DD

:clock1: **total hours spent this week by all contributors**: [N]h

:tada: **achievements**:

- **[Theme title]:** [1-3 sentence narrative with inline links to MRs and issues]
- **[Theme title]:** [1-3 sentence narrative with inline links to MRs and issues]

:issue-blocked: **blockers**:

- [Specific blocker with link to blocking MR/issue]

:arrow_forward: **next**:

- [Specific next step with link]
```

## Important Rules

- Only include work items that had actual activity in the lookback window. Do not include stale items.
- Cross-check MR relevance: if an MR is linked to an issue but is about a different topic (e.g. a RuboCop cop for URL routing linked to a state management issue), exclude it.
- Do not fabricate hour estimates without basis. If uncertain, state the assumption.
- When the user provides co-worker updates, incorporate their hours into the total and their work into the achievements.
- Use GitLab markdown link syntax: `[!MR_IID](url)` and `[#issue_IID](url)`.
Last modified July 6, 2026: Make skill prompts agent-agnostic (dd60a5ee)