src/main/resources/targets/claude/skills/core/internal/pr/x-internal-render-pr-body/SKILL.md
Renders PR body Markdown from existing disk artifacts using one of two templates. --kind=implementation: reads review/verify/telemetry artifacts for a story and emits a structured implementation PR body. --kind=backlog: reads epic/map artifacts and emits a scaffolding PR body. Fail-open: absent artifacts produce human-readable placeholders, never audit-sentinel strings. Internal — invoked only by x-create-pr and x-create-feature.
npx skillsauth add edercnj/ia-dev-environment x-internal-render-pr-bodyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
🔒 INTERNAL SKILL — Invoked only by other skills via the Skill tool. Not user-invocable.
Renders a PR body Markdown file from existing on-disk artifacts (review, verify, telemetry,
commits) and writes it to --out. Consumed by x-create-pr (kind=implementation) and
x-create-feature (kind=backlog). Fail-open: any missing source produces a human-readable
placeholder — never an audit-sentinel string recognized by audit-pr-evidence.sh.
| Parameter | Required | Description |
| :--- | :--- | :--- |
| --kind | Yes | implementation or backlog |
| --story-id | When --kind=implementation | Pattern story-XXXX-YYYY |
| --epic-id | When --kind=backlog | Pattern epic-XXXX or EPIC-XXXX |
| --out | Yes | Absolute path for output Markdown file |
| Exit | Code | Condition |
| :--- | :--- | :--- |
| 0 | OK | Body rendered and written successfully |
| 1 | INVALID_KIND | --kind absent or not implementation/backlog |
| 2 | OPERATIONAL_ERROR | template missing, write permission denied, path traversal detected |
| 3 | INVALID_SCOPE | --story-id absent for --kind=implementation; --epic-id absent for --kind=backlog |
Every absent artifact produces a human-readable placeholder. Permitted placeholders:
(pending) — review artifacts not yet produced(not yet run) — verify gate not yet executed(no telemetry available) — events.ndjson absent or empty(none) — no tasks or commits found(no commits) — git log returns emptyForbidden placeholder values (would trigger audit-pr-evidence.sh): story-XXXX-YYYY,
EPIC-XXXX, any pattern matching story-[0-9]{4}-[0-9]{4} as a verdict/decision value.
This skill is internal — never typed by a user. Callers use Rule 13 INLINE-SKILL pattern:
Skill(skill: "x-internal-render-pr-body", args: "--kind=implementation --story-id story-XXXX-YYYY --out /abs/path/body.md")
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh start x-internal-render-pr-body Phase-0-Args
Parse and validate all arguments:
--kind, --story-id, --epic-id, --out from argv.--kind:
case "$KIND" in
implementation|backlog) ;;
*) echo "INVALID_KIND: --kind is required (implementation|backlog)" >&2; exit 1 ;;
esac
if [[ "$KIND" == "implementation" && -z "$STORY_ID" ]]; then
echo "INVALID_SCOPE: --story-id required for --kind=implementation" >&2; exit 3
fi
if [[ "$KIND" == "backlog" && -z "$EPIC_ID" ]]; then
echo "INVALID_SCOPE: --epic-id required for --kind=backlog" >&2; exit 3
fi
--story-id format (kind=implementation): ^story-[0-9]{4}-[0-9]{4}$.--out and verify it stays within ${REPO_ROOT} (Rule 06 J6 — path traversal):
REPO_ROOT=$(realpath "$CLAUDE_PROJECT_DIR")
OUT_CANONICAL=$(realpath --canonicalize-missing "$OUT")
if [[ "$OUT_CANONICAL" != "$REPO_ROOT"* ]]; then
echo "OPERATIONAL_ERROR: --out path traversal detected: $OUT" >&2; exit 2
fi
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh end x-internal-render-pr-body Phase-0-Args ok
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh start x-internal-render-pr-body Phase-1-Gather
Read 7 data sources (kind=implementation only; backlog uses a different set — see Phase 1b in §Backlog extension). Build intermediate JSON envelope. Apply fail-open fallbacks.
Locate story-{storyId}.md via PathResolver (searches ai/epics/*/, plans/epic-XXXX/).
Parse Gherkin Cenário: headings for acceptance criteria list.
Fallback: acceptanceCriteria: [] (empty list).
Locate review-story-{storyId}.md under ai/epics/epic-XXXX-*/plans/ (v4) or plans/epic-XXXX/plans/ (v3).
Parse YAML-when-available: if head -1 <file> returns --- (YAML frontmatter), use
yq '.verdict' <file> (EPIC-0067 structured verdict). Otherwise, fallback regex:
grep -oP '(?<=\*\*Verdict:\s)(GO|NO-GO)' "$REVIEW_FILE" | head -1
Fallback if file absent or regex fails: specialistVerdict: "(pending)".
Locate techlead-review-story-{storyId}.md. Same YAML-when-available logic.
Fallback regex: grep -oP '(?<=\*\*Decision:\s)(GO|NO-GO)'.
Fallback: techleadDecision: "(pending)".
Locate reports/verify-envelope-{storyId}.json. Parse via jq:
jq -r '.testsResult, .coverageLine, .coverageBranch' "$ENVELOPE"
Fallback per field: "(not yet run)".
Locate reports/story-completion-report-{storyId}.md. Parse task table rows:
grep -oP 'TASK-[0-9]{4}-[0-9]{4}-[0-9]{3}' "$REPORT" | sort -u | tr '\n' ', '
Fallback: taskIds: "(none)".
Run git log origin/develop..HEAD --oneline in REPO_ROOT. Capture stdout as commit list.
Fallback: commitsList: "(no commits)".
Capture:
orchSha: git rev-parse HEADinvocationSkill: x-implement-storyphase1Artifacts: list files matching ai/epics/*/plans/*-{storyId}.mdphase3Artifacts: list files matching ai/epics/*/reports/*-{storyId}.*Escape all string values: replace | with \|, backticks with ```, newlines with space.
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh end x-internal-render-pr-body Phase-1-Gather ok
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh start x-internal-render-pr-body Phase-2-Telemetry
Invoke scripts/telemetry-consolidate.sh (story-0066-0002) for the story scope:
TEL_JSON=$(scripts/telemetry-consolidate.sh --story="$STORY_ID" --format=json 2>/tmp/tel-err.txt)
TEL_EXIT=$?
TEL_EXIT=0: parse $TEL_JSON for activeMs, elapsedMs, events, tasks[], topTools[]. Incorporate into envelope.TEL_EXIT=1 (NO_TELEMETRY): set storyActiveMin=(no telemetry available), storyElapsedMin=(no telemetry available), storyEventCount=(no telemetry available), tasks=[], topTools=[]. Emit WARNING to stderr.TEL_EXIT=2 (OPERATIONAL_ERROR): same as exit 1 (warning + placeholder). Do NOT abort — telemetry is non-blocking per RULE-002.Convert activeMs/elapsedMs to minutes: floor(ms / 60000).
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh end x-internal-render-pr-body Phase-2-Telemetry ok
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh start x-internal-render-pr-body Phase-3-Render
Select template based on --kind:
case "$KIND" in
implementation) TEMPLATE_NAME="_TEMPLATE-PR-IMPLEMENTATION.md" ;;
backlog) TEMPLATE_NAME="_TEMPLATE-PR-BACKLOG.md" ;;
esac
TEMPLATE_PATH="$CLAUDE_PROJECT_DIR/.claude/templates/$TEMPLATE_NAME"
If $TEMPLATE_PATH not found → emit OPERATIONAL_ERROR: template missing: $TEMPLATE_PATH and exit 2.
Invoke x-internal-write-report via Rule 13 Pattern 1 (INLINE-SKILL):
Skill(skill: "x-internal-write-report", args: "--template $TEMPLATE_PATH --data <json-envelope> --output $TEMP_OUT")
$TEMP_OUT is a temp file under ${REPO_ROOT}/.claude/tmp/pr-render-$STORY_ID.md.
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh end x-internal-render-pr-body Phase-3-Render ok
Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh start x-internal-render-pr-body Phase-4-Write
Atomic write: move temp file to final --out path:
mv "$TEMP_OUT" "$OUT_CANONICAL" 2>/tmp/write-err.txt || {
echo "OPERATIONAL_ERROR: write permission denied or disk full: $(cat /tmp/write-err.txt)" >&2
exit 2
}
echo "$OUT_CANONICAL"
On success, emit the final path to stdout and exit 0.
<!-- TELEMETRY: phase.end -->Bash command: $CLAUDE_PROJECT_DIR/.claude/hooks/telemetry-phase.sh end x-internal-render-pr-body Phase-4-Write ok
Executed only when --kind=backlog. Reads backlog-specific sources to build the backlog
JSON envelope (distinct from the implementation envelope built in Phase 1).
Locate epic-XXXX.md via PathResolver (searches ai/epics/epic-XXXX-*/, plans/epic-XXXX/).
Parse:
summary: first paragraph under ## 1. Contexto & Escopo or ## 1.1 Problemastories: table rows in ## 9.2 Stories — extract Phase, Story ID, Layer, Bloqueada porsuccessMetrics: bullet items under ## 5.2 Métricas Quantitativas or ## Métricas de SucessooutOfScopeList: bullet items under section containing "Fora do escopo"Escape all string values before JSON injection: replace | with \|, backticks with \`, newlines with space.
Fallbacks: summary: "(no summary)", stories: [], successMetrics: ["(no metrics declared)"], outOfScopeList: "(not documented)".
Locate IMPLEMENTATION-MAP.md in the epic directory. Parse:
criticalPath: regex \*\*Critical path.*?:\*\*\s*(.+) or Caminho crítico.*?:\s*(.+)maxParallelism: regex \*\*Maximum parallelism.*?:\*\*\s*(\d+) or Paralelismo máximo.*?:\s*(\d+)maxParallelPhase: regex \(Phase\s+([\w ]+)\) after maxParallelismtotalPhases: count of ## Phase N headersIf IMPLEMENTATION-MAP.md absent:
echo "WARN: IMPLEMENTATION-MAP.md not found for ${EPIC_ID}" >&2
criticalPath="(map missing)"
maxParallelism=0
totalPhases=0
Search for spec file:
SPEC=$(find "${REPO_ROOT}" -name "spec-*.md" -path "*/epic-XXXX-*/*" 2>/dev/null | head -1)
If found: specPath=$(realpath --relative-to="${REPO_ROOT}" "$SPEC"), specSha=$(git rev-parse "HEAD:${specPath}" 2>/dev/null || echo "(unknown)").
If not found: specPath="(spec not found)", specSha="(unknown)".
for state_file in "${REPO_ROOT}"/ai/epics/*/execution-state.json; do
status=$(jq -r '.status // empty' "$state_file" 2>/dev/null)
if [[ "$status" == "Em Andamento" ]]; then
epic_id=$(jq -r '.epicId // empty' "$state_file" 2>/dev/null)
coordinations+="{\"epicId\":\"$epic_id\",\"status\":\"in_progress\"}"
fi
done
Fallback if none: coordinations: [{"epicId":"(none)","status":"none","hotFiles":"","risk":"none"}].
| Scenario | Action |
| :--- | :--- |
| --kind absent/invalid | Exit 1 INVALID_KIND |
| --story-id absent for implementation | Exit 3 INVALID_SCOPE |
| --out path traversal | Exit 2 OPERATIONAL_ERROR: path traversal |
| Template file missing | Exit 2 OPERATIONAL_ERROR: template missing |
| Write permission denied | Exit 2 OPERATIONAL_ERROR: write permission denied |
| telemetry-consolidate.sh exit 1/2 | WARNING + placeholder (continue) |
| Any artifact absent | Placeholder per RULE-004 (continue) |
| Skill | Relationship |
| :--- | :--- |
| x-create-pr | Primary caller for --kind=implementation |
| x-create-feature | Caller for --kind=backlog (story-0066-0006) — RULE-007: backlog PR ## Orchestrator Evidence is reduced (no Story IDs; accrues in subsequent story PRs) |
| x-internal-write-report | Delegate for template rendering (Phase 3) |
| scripts/telemetry-consolidate.sh | Telemetry aggregator (Phase 2, story-0066-0002) |
| _TEMPLATE-PR-IMPLEMENTATION.md | Template consumed by Phase 3 (story-0066-0001) |
| _TEMPLATE-PR-BACKLOG.md | Template for backlog kind (story-0066-0001) |
Haiku eligibility (Rule 23 §criterion a): utility without design reasoning — reads files, formats data, writes output. No architectural choices. Upgrade to sonnet/opus must be justified in this section with concrete rationale.
testing
Scaffolds a Helidon SE/MP service with routing, health, config, Dockerfile, and tests.
tools
Generates a Picocli @Command with subcommands, options, converters, and unit tests.
testing
Scaffolds a Micronaut service with @Controller, DI, health, Dockerfile, and tests.
testing
Scaffolds a Helidon SE/MP service with routing, health, config, Dockerfile, and tests.