Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 269 additions & 0 deletions .claude/skills/enhance-claude-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
---
name: enhance-claude-docs
description: Analyze recent PR review comments and update Claude documentation files with new insights. Fetches merged, open, and closed PRs from the last N days, extracts reviewer feedback, and proposes documentation improvements. Triggers on "update claude docs", "enhance docs from PRs", "analyze PR comments".
---

# Enhance Claude Docs

Analyzes PR review comments from `UiPath/uipath-typescript` and updates Claude documentation files (`CLAUDE.md`, `Agents.md`, `agent_docs/`) with documentation-worthy insights not already captured.

---

## Arguments

- `days_back` (positional, default: `7`) — how many days back to scan for PR activity.

Example invocations:
- `/enhance-claude-docs` — last 7 days
- `/enhance-claude-docs 14` — last 14 days

---

## Step 1: Compute Date Range

Compute the start date for the PR search. Handle both macOS and Linux date commands:

```bash
# Try macOS first
START_DATE=$(date -v-${DAYS_BACK}d +%Y-%m-%d 2>/dev/null) || \
START_DATE=$(date -d "${DAYS_BACK} days ago" +%Y-%m-%d 2>/dev/null)
END_DATE=$(date +%Y-%m-%d)
```

Store `START_DATE` and `END_DATE` for use in the PR body later.

---

## Step 2: Fetch PRs

Fetch all PRs updated in the date range:

```bash
gh api "repos/UiPath/uipath-typescript/pulls?state=all&sort=updated&direction=desc&per_page=100" \
--jq "[.[] | select(.updated_at >= \"${START_DATE}\") | {number, title, state, user: .user.login, updated_at}]"
```

If no PRs found, report "No PRs found in the last N days" and stop.

---

## Step 3: Fetch Review Threads via GraphQL

Use GitHub's GraphQL API to fetch **review threads** (not individual comments) for each PR. This gives us thread resolution status and the full conversation in one call.

### GraphQL query (batch per PR)

```bash
gh api graphql -f query='
{
repository(owner: "UiPath", name: "uipath-typescript") {
pullRequest(number: {pr_number}) {
title
state
author { login }
reviewThreads(first: 100) {
nodes {
isResolved
isOutdated
path
line
comments(first: 30) {
nodes {
author { login }
body
createdAt
}
}
}
}
}
}
}'
```

### Thread classification

For each thread, classify it into one of three buckets:

| Bucket | Criteria | Action |
|--------|----------|--------|
| **Resolved** | `isResolved: true` | Analyze for insights |
| **Effectively resolved** | `isResolved: false`, but has replies where the PR author acknowledged the feedback (e.g., "done", "fixed", "changed to X", "good point, updated", or any reply indicating the feedback was accepted and acted upon) | Analyze for insights |
| **Unresolved / Rejected** | `isResolved: false`, and either no replies, or the PR author pushed back / debated without acting on it, or the thread is an open question with no conclusion | **Skip entirely** |

**Important:** Do NOT use keyword matching for the "effectively resolved" bucket. Read the full thread conversation and use semantic understanding to judge whether the PR author acknowledged and acted on the feedback. The signal could be anything — a one-word "done", a detailed explanation of what they changed, or even just agreement followed by a code change.

### Additional filtering

After thread classification, also discard threads where:
- All comments are from bots (user login ends with `[bot]`)
- The reviewer's comment is fewer than 10 characters (too short to contain insight)
- The thread is purely automated (`/`, `<!--` prefixes)

Collect all remaining **resolved + effectively resolved** threads with their PR context (PR number, title, state).

---

## Step 4: Read Current Documentation

Read all five documentation files:

1. `CLAUDE.md`
2. `Agents.md`
3. `agent_docs/architecture.md`
4. `agent_docs/conventions.md`
5. `agent_docs/rules.md`

---

## Step 5: Analyze Threads for Insights

For each resolved/effectively-resolved thread, perform a two-stage analysis:

### Stage 1: Validity and resolution extraction

Read the **full thread conversation** and determine:

1. **Was the feedback valid?** — Did the reviewer raise a legitimate concern about a pattern, convention, architecture decision, or quality issue? Or was it a misunderstanding, a personal preference, or something the PR author correctly pushed back on?
2. **What was the resolution?** — If valid, what specifically changed? Extract the concrete action taken (e.g., "switched from NetworkError to ErrorFactory", "moved folderId from positional param to options object", "added unit test for bound methods").
3. **Is it generalizable?** — Is this a one-off fix for this specific PR, or does it reveal a pattern/rule that applies to future work?

Skip threads where the feedback was invalid, the resolution is unclear, or the lesson is not generalizable.

### Stage 2: Documentation mapping

For each thread that passes Stage 1, determine if it contains a documentation-worthy insight:

| Signal | Target file |
|--------|-------------|
| Reviewer correcting a pattern violation not yet in rules | `agent_docs/rules.md` |
| Explaining WHY a convention exists or should be followed | `agent_docs/conventions.md` |
| New project structure info, service patterns, or architecture decisions | `agent_docs/architecture.md` |
| New commands, quick-reference items, or workflow changes | `Agents.md` |
| Top-level pointers or high-level project changes (rare) | `CLAUDE.md` |

### Ignore (skip these)

- One-off bug fixes with no general lesson
- Typo corrections or nit fixes
- Insights already documented in the existing files
- Subjective style preferences without team consensus
- Threads where the resolution was just "removed" or "deleted" with no broader lesson

### Deduplication

If multiple threads across different PRs express the same insight, consolidate into a single documentation change and cite all source PRs.

---

## Step 6: Propose and Apply Changes

If no actionable insights are found, report:

```
No documentation-worthy insights found in {X} PRs with {Y} comments from {START_DATE} to {END_DATE}.
```

And stop. Do not create a PR.

If actionable insights exist:

1. For each insight, determine the correct file and section.
2. Edit the files using the Edit tool. Follow existing formatting, heading levels, and conventions in each file.
3. For `agent_docs/rules.md`, add new items under the appropriate "NEVER" subsection or create a new subsection if needed. Follow the existing pattern: bold "NEVER" + action, followed by explanation with rationale.
4. For `agent_docs/conventions.md`, add to the relevant section or create a new subsection following existing patterns.
5. For `agent_docs/architecture.md`, update tables or sections as appropriate.
6. For `Agents.md`, update the quick reference or add new sections.

---

## Step 7: Create or Update PR

### Check for existing PR

```bash
gh pr list --repo UiPath/uipath-typescript --label "claude-docs-update" --state open --json number,headRefName
```

### Ensure label exists

```bash
gh label create "claude-docs-update" --repo UiPath/uipath-typescript --description "Auto-generated Claude docs update from PR review analysis" --color "0E8A16" 2>/dev/null || true
```

### Branch naming

```bash
BRANCH_NAME="claude-docs-update/$(date +%Y-%m-%d)"
```

### If existing open PR found

1. Check out the existing PR branch.
2. Commit changes with message: `docs: update claude docs from PR review analysis (${START_DATE} to ${END_DATE})`
3. Push to the existing branch.
4. Update the PR body with the new analysis using `gh pr edit`.

### If no existing PR

1. Create and check out the new branch from `main`.
2. Stage and commit all changed documentation files.
- Commit message: `docs: update claude docs from PR review analysis (${START_DATE} to ${END_DATE})`
3. Push the branch.
4. Create the PR:

```bash
gh pr create \
--repo UiPath/uipath-typescript \
--title "docs: update Claude docs from PR review analysis" \
--label "claude-docs-update" \
--reviewer "shreyash0502" \
--body "$(cat <<'EOF'
## Summary
Weekly analysis of PR comments ({START_DATE} -> {END_DATE}).
Analyzed {X} PRs with {Y} comments. Found {Z} actionable insights.

## Changes
### {file_path}
- **{Change description}**
Source: PR #{N} -- @{reviewer} commented on `{file}:{line}`:
> "{original comment}"

### No changes
- {files not modified} -- no relevant insights found

## PRs Analyzed
| PR | Title | State | Comments |
|----|-------|-------|----------|
| #{N} | {title} | {state} | {count} |
EOF
)"
```

**PR body rules:**
- Replace all `{placeholders}` with actual values.
- The **Changes** section must list every file modified with the specific change, source PR, reviewer, and original comment quote.
- The **No changes** section must list files that were read but had no relevant insights.
- The **PRs Analyzed** table must list every PR that was fetched, regardless of whether it yielded insights.
- State values: `merged`, `open`, `closed`.

---

## Output

After completion, report:

```
## Claude Docs Enhancement Summary

**Date range:** {START_DATE} to {END_DATE}
**PRs analyzed:** {X}
**Comments reviewed:** {Y}
**Actionable insights:** {Z}

### Changes made
- {file}: {brief description of changes}

### PR
{PR URL or "No PR created -- no actionable insights found"}
```
43 changes: 43 additions & 0 deletions .github/workflows/claude-docs-update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Claude Docs Update

on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am UTC
workflow_dispatch:
inputs:
days_back:
description: 'Number of days to look back for PR comments'
required: false
default: '7'

jobs:
enhance-docs:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
Comment thread
ninja-shreyash marked this conversation as resolved.

steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0

- name: Ensure label exists
run: gh label create claude-docs-update --color 0E8A16 --description "Automated Claude docs enhancement" --force
env:
GH_TOKEN: ${{ github.token }}

- name: Enhance Claude docs
id: claude
uses: anthropics/claude-code-action@094bd24d575e7b30ac1576024817bf1a97c81262 # v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
additional_permissions: |
contents: write
pull-requests: write
issues: write
prompt: /enhance-claude-docs ${{ inputs.days_back || '7' }}
Loading