graphite-merge-queue
Operate the Graphite Merge Queue — enqueue PRs via label, dequeue, monitor queue status, and reason about stacked-PR queueing. Use when the user mentions Graphite merge queue, "merge when ready", queueing a PR, dequeueing, fast-track, the merge-queue label, "enqueue", "the queue", or when they ask to merge a PR/stack through Graphite (not directly). Triggers on phrases like "queue this PR", "add to merge queue", "enqueue stack", "remove from queue", "why didn't my PR merge", and on edits to `.please/config.yml` under `graphite.merge-queue`.
What this skill does
# Graphite Merge Queue — Label-Based Enqueueing
This skill covers the **runtime** operation of Graphite's merge queue: adding/removing the merge label, reading queue config from `.please/config.yml`, and reasoning about stacked-PR enqueue cascade behavior.
For one-time setup (enabling the queue, configuring branch protection, choosing rebase vs squash), use the `graphite-setup` skill instead.
Source docs (cite when proposing actions):
- [Get started with Merge Queue](https://graphite.com/docs/get-started-merge-queue)
- [Set up the Merge Queue](https://graphite.com/docs/set-up-merge-queue)
- [Merge queue integration](https://graphite.com/docs/setup-merge-queue-integration)
## Mental model
- The merge queue **takes ownership of the merge** once a PR is enqueued. Graphite rebases the PR onto trunk, reruns required CI, and merges only after CI passes.
- **One label = one queue ticket.** Adding the configured merge label to a PR enqueues it. Removing the label dequeues it. There is no separate `/queue` command on Graphite's side — the label IS the queue API.
- **`merge when ready`**: if the label is applied before the PR is approved or CI passes, Graphite enables "merge when ready" and queues automatically when the PR becomes mergeable.
- **Stacks cascade.** Labeling a PR mid-stack also labels its descendants (upstack), and Graphite separately enqueues all ancestors (downstack) as queue dependencies — you cannot merge a parent without its children getting queued, and you cannot merge a child until its ancestors land. Removing the label cascades upstack in the same way (descendants drop out of the queue); downstack ancestors are unaffected.
> **Graphite stack terminology.** *Downstack* = toward trunk (ancestors). *Upstack* = away from trunk (descendants). Label propagation cascades **upstack**; queue dependencies pull in **downstack** ancestors.
- **Fast-track is single-PR only.** It does not apply to stacks. It still requires a rebase + CI rerun — it just jumps the queue position.
- **A Graphite account is required.** If the user labeling the PR has no Graphite account, the queue removes the label and prompts for account creation. Treat that as "labeled by the wrong user," not a queue bug.
## Repos that don't use Graphite's merge queue
Graphite supports four merge-queue postures. The label-based flow in this skill applies **only to mode `graphite`** — do not blindly apply a label in the other modes; you'll either no-op (no queue exists) or break the active queue (e.g. labeling a PR in a GitHub-native queue repo confuses operators and changes nothing).
| `merge-queue.mode` | Meaning | What to do when the user says "merge this PR" |
|---|---|---|
| `graphite` | Graphite's queue is enabled; label triggers enqueue | Apply the configured merge label (the rest of this skill) |
| `github-native` | GitHub's native merge queue is enabled | `gh pr merge --auto --squash` (or whatever strategy) — GitHub queues automatically. Do **not** apply the Graphite label; it does nothing. |
| `external` | Repo uses Mergify / Kodiak / etc. | Apply that tool's enqueue mechanism (usually its own label like `mergify-merge`). Defer to the external tool's docs; do not apply Graphite's label. |
| `none` (default) | No queue at all | Merge directly: `gt submit --merge` (Graphite UI "Merge stack") for stacks, or `gh pr merge --squash` for single PRs. |
Detect the active mode from `.please/config.yml` (see below). If it isn't set, **ask once** rather than assuming `graphite`. Choosing the wrong mode silently is worse than a one-line question.
## Reading merge-queue config from `.please/config.yml`
The label name and mode are repository-configurable. Read both from `.please/config.yml`:
```yaml
graphite:
enabled: true
merge-queue:
mode: graphite # graphite | github-native | external | none
label: "merge-queue" # used only when mode: graphite (must match Graphite settings)
# remove-label: "merge-queue-remove" # optional: separate dequeue label
```
**Bail-out check (run first):** if `graphite.enabled` is explicitly `false` in `.please/config.yml`, do not read or act on any `merge-queue` config — the repo has opted out of Graphite. The centralized parser sets `GRAPHITE_DISABLED=1` in that case (see [Centralized parser](#centralized-parser--scriptsread-merge-queue-configsh) below); when you see that, stop and tell the user the repo is opted out.
**Mode resolution order** (env var takes precedence — it's an explicit per-invocation override):
1. The `GRAPHITE_MERGE_QUEUE_MODE` environment variable.
2. `graphite.merge-queue.mode` in `.please/config.yml`.
3. Fall back to empty (and ask the user) — assume no queue rather than silently labeling.
**Label resolution order** (env var takes precedence; only meaningful when effective mode is `graphite`):
1. The `MERGE_QUEUE_LABEL` environment variable.
2. `graphite.merge-queue.label` in `.please/config.yml`.
3. Fall back to `merge-queue` (the most common default).
If `mode` is unset, ask: "Which merge queue does this repo use — Graphite's, GitHub-native, an external tool, or none?" — then offer to persist the answer.
### Centralized parser — `scripts/read-merge-queue-config.sh`
The plugin ships a single shell script that reads the disabled gate, mode, and label from `.please/config.yml` with one depth-tracked awk pass. Both this skill and the `/graphite:merge-queue` slash command call it; do not re-implement the parsing.
```bash
# Outputs three KEY=VALUE lines you can `eval`.
eval "$("${CLAUDE_PLUGIN_ROOT}/scripts/read-merge-queue-config.sh")"
# Variables now set:
# GRAPHITE_DISABLED — 1 iff graphite.enabled: false at the immediate
# child of graphite: (else 0).
# MERGE_MODE — graphite.merge-queue.mode, or empty.
# MERGE_LABEL — graphite.merge-queue.label, or empty.
# Apply env-var overrides:
MERGE_MODE="${GRAPHITE_MERGE_QUEUE_MODE:-$MERGE_MODE}"
MERGE_LABEL="${MERGE_QUEUE_LABEL:-${MERGE_LABEL:-merge-queue}}"
```
How the parser works (read `scripts/read-merge-queue-config.sh` for the awk):
- Tracks the indent of the first child of `graphite:` so only direct children (`enabled`, `merge-queue`) match — nested `enabled` keys (e.g. `graphite.merge-queue.enabled`) cannot trigger a false bail-out.
- Tracks the indent of the first child of `merge-queue:` the same way, so only direct children (`mode`, `label`) are read.
- Strips inline `# comment` trailers and surrounding quotes from the value.
Prefer `yq` if available (`yq '.graphite.merge-queue.label' .please/config.yml`), but never make `yq` a hard requirement — many repos won't have it installed. The shell script is the no-dependency fallback.
> **Known limitation:** the comment-stripping regex (`[[:space:]]+#`) does not respect quoted strings. A label like `"feature # tag"` would be truncated at the inner ` #`. Workaround for affected users: set `MERGE_QUEUE_LABEL` in the environment — env-var resolution happens before the YAML parse. If real-world users hit this, swap the parser for a quote-aware implementation in one place (`scripts/read-merge-queue-config.sh`).
## Enqueueing a PR (the golden path)
The label is the API. Use `gh` to apply it:
```bash
# 1. Confirm the PR is mergeable (or will be, with "merge when ready").
gh pr view --json number,state,mergeable,reviewDecision,statusCheckRollup
# 2. Apply the configured merge label.
gh pr edit --add-label "$MERGE_LABEL"
# 3. Verify Graphite picked it up — the label should still be present after a few seconds.
# If Graphite strips it, the user labeling the PR likely lacks a Graphite account.
gh pr view --json labels --jq '.labels[].name'
```
Default to operating on the **current branch's PR** unless the user names one. Use `gh pr view` without arguments — `gh` resolves the PR from the checked-out branch.
### Enqueueing a whole stack
When the user says "queue the stack" in a Graphite repo:
1. Run `gt ls` to show the stack shape.
2. IdeRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.