Skip to content
Development
Command

/phase-6-report

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

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/phase-6-report

Context preview

What this command does when you run it.

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

Command definition

phase-6-report.md
user-invocable: false

install: core

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

/orchestrate — Phase 6: Consolidated Report

Phase 6: Consolidated Report

After ALL issues reach terminal state AND cleanup completes, present a final summary.

Step 6A: Collect trajectory data

for NUM in {all_completed_issue_numbers}; do
  gh api repos/{GH_REPO}/issues/${NUM}/comments \
    --jq '.[] | select(.body | contains("<!-- FORGE:TRAJECTORY -->")) | .body' 2>/dev/null
done

Aggregate into the batch-level analytics for Step 6B.

**Also collect the machine-readable summary cards** (embedded in each issue's `FORGE:TRAJECTORY` comment by `/work-on` close phase as a `<!-- FORGE:CARD: v1 sha:... b64:... -->` line). These power the per-issue and batch cards in Step 6C.

**CODEC PATH (forge#1727)**: Cards are now Base64url-encoded. Use the protocol CLI's `parse` subcommand to decode them — do NOT use the old `sed -n 's/.*<!-- FORGE:CARD \(.*\) -->.*/\1/p'` regex extraction, which only worked for the deprecated inline-JSON form:

CARDS=""
for NUM in {all_completed_issue_numbers}; do
  # Fetch the TRAJECTORY comment body for this issue
  TRAJ_BODY=$(gh api repos/{GH_REPO}/issues/${NUM}/comments \
    --jq '[.[] | select(.body | contains("FORGE:CARD:"))] | last | .body // ""' 2>/dev/null || true)
  if [ -n "$TRAJ_BODY" ]; then
    # Decode via protocol CLI — handles both Base64url form (forge#1727) and gracefully
    # exits 1 (skips) for pre-migration inline-JSON entries.
    # The codec ships with ForgeDock, not with the consumer repo: resolve it from the install root.
    _l="$(readlink -f "$HOME/.claude/commands/work-on.md" 2>/dev/null || true)"; _l="${_l%/commands/work-on.md}"; CODEC_CLI=""
    for _c in '${CLAUDE_PLUGIN_ROOT}' "${FORGE_ROOT:-}" "${FORGEDOCK_HOME:-}" "${FORGE_HOME:-}" "$_l"; do case "$_c" in /*) [ -z "$CODEC_CLI" ] && [ -f "$_c/packages/protocol/src/cli.js" ] && CODEC_CLI="$_c/packages/protocol/src/cli.js" ;; esac; done
    CARD=$( [ -n "$CODEC_CLI" ] && printf '%s\n' "$TRAJ_BODY" | node "$CODEC_CLI" parse --type CARD 2>/dev/null | jq -c '.payload // .' 2>/dev/null || true)
    [ -n "$CARD" ] && CARDS="${CARDS}${CARD}"$'\n'
  fi
done
# CARDS is now a newline-delimited list of per-issue JSON objects decoded from FORGE:CARD payloads.
# Skip any issue whose card is absent — pre-card runs or non-merged terminal states degrade gracefully.

Step 6A.5: Collect merge-ready PRs (`workflow:awaiting-merge`) <!-- Added: forge#1811 -->

**Why a separate collection pass**: `workflow:awaiting-merge` issues are open (their PR hasn't merged yet), so they are excluded from `{all_completed_issue_numbers}` above — that set only contains issues that reached a closed/merged terminal state. Iterate the full batch issue set (`{all_batch_issue_numbers}` — same prose-variable used by the batch-wide loops in `phase-4-execution.md`) instead, and filter to the awaiting-merge label.

For each awaiting-merge issue, resolve its open PR using the `"Closes #N"`-anchored search established by forge#1634/#1646 — **do not** use a bare-number `search "${NUM} in:body"`, which can false-positive on changelogs or cross-references and resolve the wrong PR:

MERGE_READY_PRS=()   # each entry: "NUM|PR_NUMBER|TITLE"

for NUM in {all_batch_issue_numbers}; do
  IS_AWAITING=$(gh issue view "$NUM" -R {GH_REPO} --json labels \
    --jq '[.labels[].name | select(. == "workflow:awaiting-merge")] | length' 2>/dev/null || echo "0")
  [ "$IS_AWAITING" -gt 0 ] || continue

  TITLE=$(gh issue view "$NUM" -R {GH_REPO} --json title --jq '.title' 2>/dev/null || echo "")

  # Anchor on "Closes #N" first (forge#1634/#1646 precedent).
  PR_NUM=$(gh pr list -R {GH_REPO} --state open --search "\"Closes #${NUM}\" in:body" \
    --json number,updatedAt --jq 'sort_by(.updatedAt) | last | .number' 2>/dev/null || echo "")
  if [ -z "$PR_NUM" ]; then
    # Fallback: a PR may close the issue via "Fixes #N"/"Resolves #N" rather than
    # "Closes #N". Use the bare number only to generate candidates, then RE-VALIDATE
    # each candidate's body against an anchored (Closes|Fixes|Resolves) #N word-boundary
    # regex before accepting it — never accept a bare mention (changelog / cross-reference),
    # which could resolve the wrong PR into the one-shot batch-merge command. This mirrors
    # the recover-orphans.md re-validation precedent. <!-- forge#1822 -->
    PR_NUM=$(gh pr list -R {GH_REPO} --state open --search "${NUM} in:body" \
      --json number,updatedAt,body \
      --jq --arg n "${NUM}" '[ .[] | select(.body | test("(?i)(close[sd]?|fix(e[sd])?|resolve[sd]?)\\s+#" + $n + "\\b")) ] | sort_by(.updatedAt) | last | .number // empty' 2>/dev/null || echo "")
  fi

  [ -n "$PR_NUM" ] && MERGE_READY_PRS+=("${NUM}|${PR_NUM}|${TITLE}")
done
# MERGE_READY_PRS now holds one entry per merge-ready PR in the batch (empty array if none).
# Feeds the "### Merge-Ready" report block and the Implementation Results table row (Step 6B).

# Pre-build the batch-merge command (rendered verbatim as {MERGE_READY_CMD} in Step 6B —
# computed here, not inside the report template, so Step 6B stays plain template text with no
# nested code fences of its own). `gh pr merge` accepts only ONE PR selector per invocation,
# so chain one `gh pr merge` per PR with && rather than passing a space-separated list (which
# `gh` rejects). <!-- forge#1838 review: BUG-3 -->
MERGE_READY_CMD=""
if [ "${#MERGE_READY_PRS[@]}" -gt 0 ]; then
  for _entry in "${MERGE_READY_PRS[@]}"; do
    _pr=$(printf '%s' "$_entry" | cut -d'|' -f2)
    [ -z "$_pr" ] && continue
    [ -n "$MERGE_READY_CMD" ] && MERGE_READY_CMD="${MERGE_READY_CMD} && "
    MERGE_READY_CMD="${MERGE_READY_CMD}gh pr merge ${_pr} --merge -R {GH_REPO}"
  done
fi

Step 6A.6: Collect blocked-on-human-merge dependents (`blocked-on-human-merge`) <!-- Added: forge#1812 -->

**Why a separate collection pass**:

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.