| name | queue-reprocess |
| description | Move failed messages from dead letter queues back to their main queue. Use when asked about "reprocess DLQ", "retry failed messages", "move DLQ messages", "republish dead letters". SKIP: diagnosing failures first (use queue-triage); checking counts (use queue-status). |
Step 0 — Load configuration
Check if /tmp/ops-suite-session/config.json exists:
- If yes, read it (pre-parsed by session-start hook).
- If no, read
${XDG_CONFIG_HOME:-$HOME/.config}/ops-suite/config.yaml (preferred) or the plugin's config.yaml (legacy), parse it, and write to /tmp/ops-suite-session/config.json for other skills to reuse.
If neither exists, tell the user to run /ops-suite:configure (or copy config.example.yaml to ~/.config/ops-suite/config.yaml and fill in their values). Stop here.
Extract:
message_broker — determines which adapter to load
orchestrator — for connecting to the broker
environments — connection details
Step 1 — Load adapter
Read the adapter file at adapters/{message_broker}.md (in this skill's directory).
If the adapter does not exist, tell the user that the message broker {message_broker} is not yet supported and stop.
Step 2 — Determine target environment
If $ARGUMENTS contains an environment name, use it. Otherwise ask the user.
Store the selected environment config as env.
Step 3 — Pre-flight: check triage
Check /tmp/ops-suite-session/last-triage.json:
If it exists and is less than 10 minutes old for the same DLQ:
- Skip triage, use cached results.
- Show: "Using triage from {minutes} ago: {summary}"
If it does not exist or is stale:
- Show: "This DLQ has not been triaged recently. Reprocessing without fixing the root cause will likely send messages back to the DLQ."
- Suggest:
→ Run /ops-suite:queue-triage {dlq_name} {env_name} first.
- Ask: "Continue anyway? (yes/no)"
Step 4 — Identify DLQ and target queue
If $ARGUMENTS contains a queue name, use it.
Otherwise, list DLQs with messages and let the user pick:
DLQs with messages:
| DLQ Name | Messages | Target Queue |
|--------------------------|----------|----------------------|
| {dlq_name} | {count} | {target_queue} |
Determine the target (main) queue by:
- Checking
x-first-death-queue header from a sample message
- Removing the DLQ suffix (e.g.,
.dlq, .dead-letter, .error)
- Asking the user to confirm the target queue
Step 5 — Verify prerequisites
Use the adapter to check:
- The DLQ exists and has messages
- The target queue exists and has consumers
- The required plugin/feature is available (e.g., shovel plugin for RabbitMQ)
If the target queue has 0 consumers, warn the user that messages will just pile up.
Step 6 — Confirm reprocessing
ALWAYS ask for explicit confirmation before moving messages.
Display:
Ready to reprocess:
Source DLQ: {dlq_name}
Target queue: {target_queue}
Messages: {count}
Method: {shovel/move/republish}
This will move {count} messages back to {target_queue}. Proceed? (yes/no)
Step 7 — Move messages
Use the adapter's preferred method (in order of preference):
- Shovel — Create a temporary shovel to move messages (RabbitMQ)
- Move — Use the Management API move feature
- Republish clean — Fetch, strip death headers, republish to target exchange
Monitor progress
After starting the move:
- Check the DLQ message count periodically
- Check the target queue message count
- Verify messages are being consumed (not just accumulating)
Step 8 — Verify completion
Once the DLQ is empty (or the expected count has been moved):
- Confirm the DLQ message count is 0 (or reduced by expected amount)
- Check the target queue for any new DLQ entries (messages failing again)
- Check consumer logs for errors
Step 9 — Cleanup
- Remove the temporary shovel (if created)
- Kill any port-forward processes
- Report the result
Step 10 — Purge (if needed)
If messages are not reprocessable (e.g., malformed payloads, already processed):
ALWAYS ask for explicit confirmation before purging.
Purge {count} messages from {dlq_name}? This is irreversible. (yes/no)
Output format
Reprocessing Summary:
DLQ: {dlq_name}
Target: {target_queue}
Environment: {env_name}
Messages moved: {count}
Method: {method}
Status: {success/partial/failed}
Post-move check:
DLQ remaining: {count}
Target queue: {count} messages, {consumers} consumers
New DLQ entries: {count} (messages that failed again)
Cleanup:
- Shovel removed: {yes/no/n/a}
- Port-forward killed: {yes/no/n/a}