Skip to content
Development
Command

/spec-doctor

Evidence-backed spec evolution — reads finding concentration for a spec file, drafts a spec diff, opens a spec-evolution PR with per-change citations

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/spec-doctor

Context preview

What this command does when you run it.

Evidence-backed spec evolution — reads finding concentration for a spec file, drafts a spec diff, opens a spec-evolution PR with per-change citations

Command definition

spec-doctor.md
description: Evidence-backed spec evolution — reads finding concentration for a spec file, drafts a spec diff, opens a spec-evolution PR with per-change citations
argument-hint: "[spec file path | \"auto\"]"
install: extras

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

/spec-doctor — Evidence-Backed Spec Evolution

**Input**: $ARGUMENTS

Closes the feedback loop from `pipeline-health` finding data into self-improving spec PRs. Reads concentrated review findings for a spec file, drafts a concrete spec diff addressing the recurring defect classes, and opens a `spec-evolution` PR whose body cites every finding that motivated each change. The human stays the authority — **spec-evolution PRs are never auto-merged**, and the eval gate must pass before merge is possible.

<!-- FORGE:SPEC_LOADED — spec-doctor.md loaded and active. Agent is bound by this spec. -->

HARD RULES — READ BEFORE ANYTHING ELSE

1. **NEVER auto-merge a spec-evolution PR.** `gh pr create` must NEVER include `--auto-merge`. The eval gate makes the proposal trustworthy; the human stays the authority. 2. **Every spec change must cite its evidence.** Each changed block in the PR body must list the finding issues that motivated it. A spec change with no cited findings is spec drift, not spec evolution. 3. **Do not widen scope beyond the concentrated-finding spec file.** One spec-doctor run = one spec file. If adjacent specs also need fixes, create separate issues. 4. **The spec diff is a proposal, not a decree.** Post it as a PR for human review. Do NOT update `commands/` files directly without going through the PR flow. 5. **NEVER use the Agent tool** — all sub-operations run inline or via `Skill(...)`.

---

Phase 0: Resolve Target Spec

0A: Parse input

If `$ARGUMENTS` is a file path matching `commands/*.md`: use that spec file directly.

If `$ARGUMENTS` is `"auto"` or empty: auto-select the worst offender from the recurrence data (see Phase 1 — run it with `--auto-select` mode and pick the top-ranked spec file).

INPUT_ARG="${ARGUMENTS:-auto}"

if echo "$INPUT_ARG" | grep -qE '^commands/'; then
  TARGET_SPEC="$INPUT_ARG"
  SELECT_MODE="explicit"
else
  TARGET_SPEC=""
  SELECT_MODE="auto"
fi

0B: Load forge.yaml

GH_REPO=$(yq '.project.owner + "/" + .project.repo' forge.yaml 2>/dev/null)
GH_FLAG="-R $GH_REPO"
REPO_PATH=$(yq '.paths.root' forge.yaml 2>/dev/null || echo ".")
STAGING_BRANCH=$(yq '.branches.staging // "staging"' forge.yaml 2>/dev/null)

0C: Ensure spec-evolution label exists

gh label create "spec-evolution" \
  --color "BFD4F2" \
  --description "Spec PR backed by eval corpus. Managed by ForgeDock." \
  --force \
  $GH_FLAG 2>/dev/null || true

---

Phase 1: Query Finding Recurrence by Spec File

1A: Collect review findings from the last 30 days

SINCE=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
  || date -v-30d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
  || python3 -c "import datetime; print((datetime.datetime.utcnow() - datetime.timedelta(days=30)).strftime('%Y-%m-%dT%H:%M:%SZ'))")

# Fetch review-finding issues closed in the 30-day window
FINDINGS_RAW=$(gh issue list $GH_FLAG \
  --label "review-finding" \
  --state closed \
  --limit 200 \
  --json number,title,body,closedAt \
  --jq ".[] | select(.closedAt >= \"$SINCE\")" 2>/dev/null || echo "[]")

TOTAL_FINDINGS=$(echo "$FINDINGS_RAW" | grep -c '"number"' 2>/dev/null || echo "0")
echo "Found $TOTAL_FINDINGS review findings in the last 30 days"

1B: Group findings by referenced spec file

Findings reference a spec file when their body contains a path matching `commands/*.md` or a link to a section of a command spec file. Extract the primary spec reference:

# For each finding, extract the first commands/*.md reference from the body
# Pattern: `commands/foo.md`, commands/foo/bar.md, or "commands/foo" in prose
echo "$FINDINGS_RAW" | jq -r '
  . |
  (.body | match("commands/[a-z0-9_/-]+\\.md").string // null) as $spec |
  if $spec then "\(.number)|\($spec)" else empty end
' 2>/dev/null | sort | uniq > /tmp/findings_by_spec.txt

# Build concentration table: spec file → count, finding numbers
declare -A SPEC_COUNTS
declare -A SPEC_FINDINGS
while IFS='|' read -r num spec; do
  [ -z "$spec" ] && continue
  SPEC_COUNTS["$spec"]=$(( ${SPEC_COUNTS["$spec"]:-0} + 1 ))
  SPEC_FINDINGS["$spec"]="${SPEC_FINDINGS[$spec]:+${SPEC_FINDINGS[$spec]},}#$num"
done < /tmp/findings_by_spec.txt

# Rank by count descending
for spec in "${!SPEC_COUNTS[@]}"; do
  echo "${SPEC_COUNTS[$spec]} $spec"
done | sort -rn > /tmp/spec_ranked.txt

echo "Spec file recurrence ranking (last 30 days):"
cat /tmp/spec_ranked.txt | head -10

1C: Resolve target spec (auto-select or validate explicit)

if [ "$SELECT_MODE" = "auto" ]; then
  # Pick the top-ranked spec file with ≥ 5 findings
  TARGET_SPEC=$(awk '$(1) >= 5 {print $(2); exit}' /tmp/spec_ranked.txt || echo "")
  if [ -z "$TARGET_SPEC" ]; then
    echo "No spec file has ≥5 findings in the last 30 days. Top offender:"
    head -1 /tmp/spec_ranked.txt
    # Use top offender even if below threshold for explicit runs
    TARGET_SPEC=$(awk 'NR==1{print $(2)}' /tmp/spec_ranked.txt || echo "")
    if [ -z "$TARGET_SPEC" ]; then
      echo "ERROR: No finding data available. Run pipeline-health first to accumulate findings."
      exit 1
    fi
    echo "Using top offender: $TARGET_SPEC (below 5-finding threshold — proceeding with explicit run)"
  else
    echo "Auto-selected worst offender: $TARGET_SPEC (${SPEC_COUNTS[$TARGET_SPEC]} findings)"
  fi
else
  # Validate explicit spec file exists
  if [ ! -f "$REPO_PATH/$TARGET_SPEC" ]; then
    echo "ERROR: Spec file not found: $REPO_PATH/$TARGET_SPEC"
    exit 1
  fi
  echo "Explicit target spec: $TARGET_SPEC"
fi

FINDING_COUNT=${SPEC_COUNTS["$TARGET_SPEC"]:-0}
FINDING_NUMBERS=${SPEC_FINDINGS["$TARGE
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.