Skip to content
Development
Command

/replay

Read-only playback of a completed pipeline run — shows FORGE annotations phase by phase with timestamps

BOOST
From plugin
forgedock
11980 skills80 commands
Install
> /plugin marketplace add RapierCraftStudios/ForgeDock
> /plugin install forgedock@forgedock

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/replay

Context preview

What this command does when you run it.

Read-only playback of a completed pipeline run — shows FORGE annotations phase by phase with timestamps

Command definition

replay.md
description: Read-only playback of a completed pipeline run — shows FORGE annotations phase by phase with timestamps
argument-hint: <issue-number>
install: extras

/replay — Pipeline Run Playback

**Input**: $ARGUMENTS (issue number)

Replay a completed pipeline run. Fetches all FORGE annotations posted during the pipeline and displays them chronologically — phase headings, timestamps, and key structured fields. Read-only: nothing is written, no labels changed.

**Agent model policy**: `model: "{DEFAULT_MODEL}"` — resolved from forge.yaml `agents.default_model`, else "sonnet" (standard tier). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` in Task/Skill spawns only on Claude Code >= 2.1.154.

---

Config Preamble

CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
if [ -f "$CONFIG_FILE" ]; then
  GH_OWNER=$(yq '.project.owner' "$CONFIG_FILE")
  GH_REPO_NAME=$(yq '.project.repo' "$CONFIG_FILE")
  GH_REPO="${GH_OWNER}/${GH_REPO_NAME}"
  GH_FLAG="-R $GH_REPO"
else
  echo "ERROR: forge.yaml not found."
  echo "Run: npx forgedock init"
  exit 1
fi

---

Step 1: Parse Input

NUMBER=$(echo "$ARGUMENTS" | grep -oP '^\s*#?\K\d+' | head -1)
if [ -z "$NUMBER" ]; then
  echo "Usage: /replay <issue-number>"
  echo "Example: /replay 42"
  exit 1
fi
echo "Replaying pipeline run for issue #${NUMBER}..."

---

Step 2: Fetch Issue Metadata

ISSUE_JSON=$(gh issue view "$NUMBER" "$GH_FLAG" \
  --json number,title,state,labels,createdAt,closedAt 2>/dev/null)

if [ -z "$ISSUE_JSON" ] || echo "$ISSUE_JSON" | grep -q '"message"'; then
  echo "ERROR: Issue #${NUMBER} not found in ${GH_REPO}."
  exit 1
fi

ISSUE_TITLE=$(echo "$ISSUE_JSON" | jq -r '.title')
ISSUE_STATE=$(echo "$ISSUE_JSON" | jq -r '.state')
ISSUE_CREATED=$(echo "$ISSUE_JSON" | jq -r '.createdAt')
ISSUE_CLOSED=$(echo "$ISSUE_JSON" | jq -r '.closedAt // "open"')
WORKFLOW_LABELS=$(echo "$ISSUE_JSON" | jq -r '[.labels[].name | select(startswith("workflow:"))] | join(", ")')

echo ""
echo "══════════════════════════════════════════════════════════════"
echo "  Pipeline Replay — #${NUMBER}: ${ISSUE_TITLE}"
echo "══════════════════════════════════════════════════════════════"
echo "  State   : ${ISSUE_STATE}"
echo "  Opened  : ${ISSUE_CREATED}"
[ "$ISSUE_CLOSED" != "open" ] && echo "  Closed  : ${ISSUE_CLOSED}"
[ -n "$WORKFLOW_LABELS" ] && echo "  Labels  : ${WORKFLOW_LABELS}"
echo "══════════════════════════════════════════════════════════════"

---

Step 3: Fetch All Comments

# One API call — returns all comments in chronological order
ALL_COMMENTS=$(gh api "repos/${GH_REPO}/issues/${NUMBER}/comments" 2>/dev/null)

if [ -z "$ALL_COMMENTS" ] || [ "$ALL_COMMENTS" = "[]" ]; then
  echo ""
  echo "  No comments on this issue. No pipeline run to replay."
  exit 0
fi

---

Step 4: Identify FORGE Annotations

# Filter to comments that contain a FORGE pipeline annotation
FORGE_COMMENTS=$(echo "$ALL_COMMENTS" | jq -c '[.[] | select(.body | test("<!-- FORGE:(INVESTIGATOR|CONTRACT|CONTEXT|ARCHITECT|BUILDER|DECOMPOSED|SUMMARY|TRAJECTORY)"))]')
FORGE_COUNT=$(echo "$FORGE_COMMENTS" | jq 'length')

if [ "$FORGE_COUNT" -eq 0 ]; then
  echo ""
  echo "  No FORGE pipeline annotations found on issue #${NUMBER}."
  echo "  This issue was not processed by the /work-on pipeline,"
  echo "  or comments were posted before pipeline annotation was introduced."
  exit 0
fi

echo ""
echo "  Found ${FORGE_COUNT} pipeline annotation(s). Playing back..."
echo ""

---

Step 5: Display Each Annotation

Phase mapping (inline): `INVESTIGATOR`→Phase 1, `CONTRACT`→Phase 3C, `CONTEXT`→Phase 3C.5, `ARCHITECT`→Phase 3C.6, `BUILDER`→Phase 3M, `DECOMPOSED`→Phase 2, `SUMMARY`→Phase C4.5, `TRAJECTORY`→Phase 7.

For each FORGE comment in chronological order, print a formatted block. Use Python for robust multiline extraction from the comment body.

echo "$FORGE_COMMENTS" | jq -c '.[]' | while IFS= read -r COMMENT; do
  BODY=$(echo "$COMMENT" | jq -r '.body')
  CREATED=$(echo "$COMMENT" | jq -r '.created_at')
  AUTHOR=$(echo "$COMMENT" | jq -r '.user.login')

  # Identify annotation type
  ANNOTATION=$(echo "$BODY" | grep -oP '(?<=<!-- )FORGE:[A-Z:]+(?= -->| -->)' | head -1)

  # Map to phase label
  case "$ANNOTATION" in
    "FORGE:INVESTIGATOR") PHASE_LABEL="Phase 1 — Investigation" ;;
    "FORGE:CONTRACT")     PHASE_LABEL="Phase 3C — Builder Contract" ;;
    "FORGE:CONTEXT")      PHASE_LABEL="Phase 3C.5 — Context Gathering" ;;
    "FORGE:ARCHITECT")    PHASE_LABEL="Phase 3C.6 — Architecture Plan" ;;
    "FORGE:BUILDER")      PHASE_LABEL="Phase 3M — Implementation" ;;
    "FORGE:DECOMPOSED")   PHASE_LABEL="Phase 2 — Decomposition" ;;
    "FORGE:SUMMARY")      PHASE_LABEL="Phase C4.5 — Shareable Summary" ;;
    "FORGE:TRAJECTORY")   PHASE_LABEL="Phase 7 — Pipeline Trajectory" ;;
    *)                    PHASE_LABEL="$ANNOTATION" ;;
  esac

  # Format timestamp: 2025-01-15T14:32:00Z → 2025-01-15 14:32 UTC
  TIMESTAMP=$(echo "$CREATED" | sed 's/T/ /; s/:[0-9][0-9]Z/ UTC/')

  echo "┌─────────────────────────────────────────────────────────────"
  echo "│  ${PHASE_LABEL}"
  echo "│  ${TIMESTAMP}  ·  @${AUTHOR}"
  echo "├─────────────────────────────────────────────────────────────"

  # Extract key fields per annotation type
  ANNOTATION="$ANNOTATION" BODY_CONTENT="$BODY" python3 - <<'PYEOF'
import re, sys, os

body = os.environ.get('BODY_CONTENT', '')

def extract(pattern, default="—"):
    m = re.search(pattern, body, re.MULTILINE | re.DOTALL)
    return m.group(1).strip() if m else default

def count_lines(header):
    m = re.search(r'### ' + header + r'\n(.*?)(?=\n###|\Z)', body, re.DOTALL)
    if not m: return 0
    return len([l for l in m.group(1).strip().splitlines() if l.strip()])

annotation = os.environ.get('ANNOTATION', '')

if annotation == "FORGE:INVESTIGATOR":
    verdict    = extract(r'\*\*Verdict\*\*:\s*(\S+)')
    confidence = extract(r'\*\*Confidence\*\*:\s*(\S+)')
    s
Read more
Ships withforgedock

ForgeDock — autonomous AI dev pipeline for Claude Code. GitHub as agent memory: issue in, PR out.

Get the whole plugin

Other commands on forgedock.