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
40 changes: 9 additions & 31 deletions .claude/skills/doc-pr-fix/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: doc-pr-fix
description: "Autonomous fixer for documentation PRs. Triggered by @claude comments on PRs targeting dev. Reads the writer's request, the doc-pr review comment, and the Vale linting comment, then applies fixes and commits. Use this skill whenever a writer tags @claude on a documentation PR — not for interactive help (use doc-help for that), but for autonomous, single-shot fixes in CI."
description: "Autonomous fixer for documentation PRs. Triggered by @claude comments on PRs targeting dev. Reads the writer's request and the doc-pr review comment, then applies fixes and commits. Use this skill whenever a writer tags @claude on a documentation PR — not for interactive help (use doc-help for that), but for autonomous, single-shot fixes in CI."
argument-hint: "[pr-number] [writer-comment]"
---

Expand All @@ -20,8 +20,7 @@ You receive:

Parse the writer's comment to determine what they want. Common patterns:

- **Fix all issues** — apply every fix from the doc-pr review comment and the Vale linting comment
- **Fix only Vale issues** — apply only fixes from the Vale linting comment
- **Fix all issues** — apply every fix from the doc-pr review comment (Dale + editorial)
- **Fix only Dale issues** — apply only Dale linting fixes
- **Fix a specific issue** — apply one targeted fix
- **Improve flow/clarity/structure** — editorial rewrite of specific content
Expand All @@ -37,34 +36,27 @@ Parse the writer's comment to determine what they want. Common patterns:
gh api repos/{owner}/{repo}/issues/$PR_NUMBER/comments --jq '.[] | select(.body | contains("Documentation PR Review")) | .body' | tail -1
```
This tells you what Dale and the editorial review flagged.
4. If the writer asks to fix Vale issues (or "all issues"), also find the Vale linting comment:
```bash
gh api repos/{owner}/{repo}/issues/$PR_NUMBER/comments --jq '.[] | select(.user.login == "github-actions[bot]" and (.body | contains("## Vale Linting"))) | .body' | tail -1
```
This gives you the Vale results table with file paths, line numbers, and rule violations.

## Step 3: Plan your work and post a progress comment

Use Todo to create a task for each discrete piece of work you need to do. Build the task list from what you learned in Steps 1–2. Each task should be concrete and trackable. Mark each task as complete as you finish it.

Example tasks for a "fix all issues" request:
- Fix Vale issues in `path/to/file.md` (N issues)
- Fix Vale issues in `path/to/other.md` (N issues)
- Fix Dale issues in `path/to/file.md` (N issues)
- Apply editorial suggestions
- Verify changes
- Commit and push

Only include tasks for what the writer actually asked for. If they said "fix only the Dale issues," your task list should contain Dale fixes, verify, and commit — no Vale tasks, no editorial tasks. The task list must reflect the writer's request exactly.
Only include tasks for what the writer actually asked for. If they said "fix only the Dale issues," your task list should contain Dale fixes, verify, and commit — no editorial tasks. The task list must reflect the writer's request exactly.

Then post a PR comment mirroring your task list so the writer can see what you're doing:

```bash
PROGRESS_COMMENT_ID=$(gh pr comment "$PR_NUMBER" --body "$(cat <<'EOF'
**Fix in progress:**

- [ ] Fix Vale issues in `path/to/file.md` (N issues)
- [ ] Fix Vale issues in `path/to/other.md` (N issues)
- [ ] Fix Dale issues in `path/to/file.md` (N issues)
- [ ] Apply editorial suggestions
- [ ] Verify changes
- [ ] Commit and push
EOF
Expand All @@ -84,7 +76,6 @@ Update the PR comment at natural milestones (after finishing each file, after co

Work through the requested fixes methodically:

- For **Vale fixes**: read `docs/CLAUDE.md` for Vale guidance (especially the two rules requiring extra care), then fix each flagged issue in order, file by file
- For **Dale fixes**: fix each flagged issue in order, file by file
- For **editorial fixes from the review**: apply the suggested changes from the review comment
- For **broader editorial requests** ("improve the flow", "make this clearer", "help with structure"): invoke `/doc-help` with the file path and the writer's request. Doc-help will analyze the document using its structured editing framework (structure, clarity, voice, surface). Since this is running in CI without an interactive writer, apply all of doc-help's suggestions autonomously rather than waiting for feedback
Expand All @@ -93,20 +84,7 @@ Work through the requested fixes methodically:
When editing:
- Use the Edit tool for targeted changes, Write for larger rewrites
- Preserve the author's meaning and intent — fix the style, don't rewrite the content
- Only change what was requested; don't fix other categories of issues even if they're on the same line (e.g., if asked to fix Vale issues, don't also fix Dale or editorial issues)

## Step 4b: Update the Vale Idioms rule

After applying fixes, check whether any Dale `idioms` violations or editorial items tagged `[idiom]` contained phrases not already in `.vale/styles/Netwrix/Idioms.yml`. For each new idiom:

1. Read `.vale/styles/Netwrix/Idioms.yml` to confirm the phrase isn't already covered (check for both exact matches and regex patterns that would match it).
2. Add a new token entry under the most appropriate category comment. Follow existing conventions:
- Use `\b` word boundaries for multi-word phrases.
- Add optional inflection suffixes where the idiom can be conjugated (e.g., `\bgets? the ball rolling\b`).
- Use single quotes around each token.
3. Include the Idioms.yml file in your commit so the Vale rule grows over time.

If no new idioms were found, skip this step.
- Only change what was requested; don't fix other categories of issues even if they're on the same line (e.g., if asked to fix Dale issues, don't also fix editorial issues)

## Step 5: Verify

Expand Down Expand Up @@ -135,8 +113,8 @@ gh api repos/{owner}/{repo}/issues/comments/$PROGRESS_COMMENT_ID \
-X PATCH -f body="$(cat <<'EOF'
**Fix complete:**

- [x] Fix Vale issues in `path/to/file.md` (N issues)
- [x] Fix Vale issues in `path/to/other.md` (N issues)
- [x] Fix Dale issues in `path/to/file.md` (N issues)
- [x] Apply editorial suggestions
- [x] Verify changes
- [x] Commit and push

Expand All @@ -152,7 +130,7 @@ Skip progress tracking only for pure explanations (e.g., "why is this flagged?")
## Behavioral Notes

- **Fix what's clear, ask about what isn't.** If a request has both obvious parts and ambiguous parts, apply the obvious fixes, commit and push those, then post a comment that summarizes what you did AND asks clarifying questions about the rest. The writer can reply with another `@claude` comment to continue.
- **Never fix issues the writer didn't ask about.** If they said "fix the Vale issues," only fix Vale issues — don't also fix Dale issues, editorial issues, or rewrite sentences for clarity, even if the fix is on the same line.
- **Never fix issues the writer didn't ask about.** If they said "fix the Dale issues," only fix Dale issues — don't also fix editorial issues or rewrite sentences for clarity, even if the fix is on the same line.
- **If a fix would substantially change the author's meaning**, skip it and explain why in your summary comment. Ask the writer how they'd like to handle it.
- **If the entire request is unclear**, don't edit anything — post a comment asking for clarification. It's better to ask one good question than to guess wrong and push unwanted changes.
- **Each `@claude` comment is a fresh invocation.** You won't remember previous runs, so always re-read the PR diff and review comment for context.
9 changes: 4 additions & 5 deletions .claude/skills/doc-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
name: doc-pr
description: "Orchestrate a documentation review for pull requests targeting dev. Runs Dale linting and editorial review on changed markdown files, then posts a structured comment to the PR. Vale linting runs separately via the vale-linter workflow (inline review comments + summary PR comment). Use this skill whenever a PR involves markdown files in docs/ and targets the dev branch — triggered automatically by the doc-pr GitHub Actions workflow on PR open, sync, or when invoked manually via /doc-pr."
description: "Orchestrate a documentation review for pull requests targeting dev. Runs Dale linting and editorial review on changed markdown files, then posts a structured comment to the PR. Vale issues are auto-fixed separately by the vale-autofix workflow. Use this skill whenever a PR involves markdown files in docs/ and targets the dev branch — triggered automatically by the doc-pr GitHub Actions workflow on PR open, sync, or when invoked manually via /doc-pr."
argument-hint: "[changed-files-csv] [pr-number]"
---

# Doc PR Review

You orchestrate a two-stage documentation review pipeline for pull requests. Your job is to run each stage, collect the results, and post a single comprehensive review comment to the PR.

Vale linting runs separately (via the vale-linter workflow) and posts inline review comments plus a summary PR comment. Do not run Vale or include Vale results in your review.
Vale issues are auto-fixed separately by the vale-autofix workflow. Do not run Vale or include Vale results in your review.

Read `docs/CLAUDE.md` before starting — it contains the writing standards and Vale guidance you need for the editorial review stage.

Expand Down Expand Up @@ -99,16 +99,15 @@ Write the full review body to `/tmp/doc-pr-review.md` using the Write tool. Foll

### Summary

N Dale issues, N editorial suggestions across N files. Vale issues are posted in a separate comment by the vale-linter workflow.
N Dale issues, N editorial suggestions across N files. Vale issues are auto-fixed separately.

---

**What to do next:**

Comment `@claude` on this PR followed by your instructions to get help:

- `@claude fix all issues` — fix all Vale, Dale, and editorial issues
- `@claude fix only the Vale issues` — fix just the Vale issues
- `@claude fix all issues` — fix all Dale and editorial issues
- `@claude help improve the flow of this document` — get writing assistance
- `@claude explain the voice issues` — understand why something was flagged

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/claude-doc-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jobs:
- Dale issues: ${{ steps.dale-post.outputs.dale_count }} (already posted as inline comments)
- PR diff is at: /tmp/pr-diff.txt

NOTE: Vale linting runs separately (vale-linter workflow) and posts inline review comments plus a summary PR comment. Do not run Vale or include Vale issues in this review.
NOTE: Vale issues are auto-fixed separately by the vale-autofix workflow. Do not run Vale or include Vale issues in this review.

INSTRUCTIONS:

Expand Down Expand Up @@ -289,7 +289,7 @@ jobs:
OWNER="${REPO%%/*}"
NAME="${REPO##*/}"

# Resolve all Dale and Vale inline comment threads
# Resolve all Dale inline comment threads
THREAD_IDS=$(gh api graphql -f query='
query($owner:String!,$name:String!,$pr:Int!) {
repository(owner:$owner,name:$name) {
Expand All @@ -300,17 +300,17 @@ jobs:
}
}
}' -f owner="$OWNER" -f name="$NAME" -F pr="$PR_NUMBER" \
--jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false and ((.comments.nodes[0].body | contains("**Dale**")) or (.comments.nodes[0].body | contains("**Vale**")))) | .id' 2>/dev/null || true)
--jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false and (.comments.nodes[0].body | contains("**Dale**"))) | .id' 2>/dev/null || true)
for TID in $THREAD_IDS; do
gh api graphql -f query='
mutation($tid:ID!) {
resolveReviewThread(input:{threadId:$tid}) { thread { isResolved } }
}' -f tid="$TID" 2>/dev/null || true
done

# Dismiss all previous Dale and Vale reviews
# Dismiss all previous Dale reviews
REVIEW_IDS=$(gh api repos/${REPO}/pulls/${PR_NUMBER}/reviews \
--jq '[.[] | select(.user.login == "github-actions[bot]" and ((.body | contains("Dale found")) or (.body | contains("Vale found")))) | .id] | .[]' 2>/dev/null || true)
--jq '[.[] | select(.user.login == "github-actions[bot]" and (.body | contains("Dale found"))) | .id] | .[]' 2>/dev/null || true)
for ID in $REVIEW_IDS; do
gh api repos/${REPO}/pulls/${PR_NUMBER}/reviews/${ID}/dismissals \
-f message="Superseded after fixes applied" -f event="DISMISS" 2>/dev/null || true
Expand Down
Loading
Loading