mirror of
https://github.com/docker/docs.git
synced 2026-04-05 10:48:55 +07:00
feat: rewrite skills/agent docs
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
20
.agents/hooks/enforce-git-hygiene.sh
Executable file
20
.agents/hooks/enforce-git-hygiene.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
# PreToolUse hook for the Bash tool.
|
||||
# Blocks dangerous git patterns that cause CI failures.
|
||||
set -euo pipefail
|
||||
|
||||
input=$(cat)
|
||||
command=$(echo "$input" | jq -r '.tool_input.command // empty')
|
||||
|
||||
if [ -z "$command" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Block 'git add .' / 'git add -A' / 'git add --all'
|
||||
# These stage package-lock.json and other generated files.
|
||||
if echo "$command" | grep -qE 'git\s+add\s+(\.|--all|-A)(\s|$|;)'; then
|
||||
echo "BLOCKED: do not use 'git add .' / 'git add -A' / 'git add --all'. Stage files explicitly by name." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
25
.agents/hooks/enforce-vendored.sh
Executable file
25
.agents/hooks/enforce-vendored.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# PreToolUse hook for Edit and Write tools.
|
||||
# Blocks edits to vendored content that must be fixed upstream.
|
||||
set -euo pipefail
|
||||
|
||||
input=$(cat)
|
||||
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
||||
|
||||
if [ -z "$file_path" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Block edits to vendored Hugo modules.
|
||||
if echo "$file_path" | grep -qE '/_vendor/'; then
|
||||
echo "BLOCKED: _vendor/ is vendored from upstream Hugo modules. Fix in the source repo instead." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Block edits to vendored CLI reference data.
|
||||
if echo "$file_path" | grep -qE '/data/cli/'; then
|
||||
echo "BLOCKED: data/cli/ is generated from upstream repos (docker/cli, docker/buildx, etc.). Fix in the source repo instead." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exit 0
|
||||
26
.agents/settings.json
Normal file
26
.agents/settings.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash .agents/hooks/enforce-vendored.sh"
|
||||
}
|
||||
],
|
||||
"description": "Block edits to vendored content (_vendor/, data/cli/)"
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash .agents/hooks/enforce-git-hygiene.sh"
|
||||
}
|
||||
],
|
||||
"description": "Block git add . and dangerous patterns"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
90
.agents/skills/check-pr/SKILL.md
Normal file
90
.agents/skills/check-pr/SKILL.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: check-pr
|
||||
description: >
|
||||
Check a single PR's CI status, review comments, and requested changes.
|
||||
Fix actionable failures and address feedback. "check PR 1234", "what's
|
||||
the status of my PR", "address review comments on #500".
|
||||
argument-hint: "<pr-number>"
|
||||
context: fork
|
||||
---
|
||||
|
||||
# Check PR
|
||||
|
||||
Do one pass over PR **$ARGUMENTS**: check CI, read reviews, fix what's
|
||||
actionable, report status.
|
||||
|
||||
## 1. Gather PR state
|
||||
|
||||
```bash
|
||||
# Overall state
|
||||
gh pr view $ARGUMENTS --repo docker/docs --json state,title,url,headRefName
|
||||
|
||||
# CI checks
|
||||
gh pr checks $ARGUMENTS --repo docker/docs --json name,state,detailsUrl
|
||||
|
||||
# Top-level reviews
|
||||
gh pr view $ARGUMENTS --repo docker/docs --json reviews,reviewDecision
|
||||
|
||||
# Inline (line-level) comments — NOT included in the above
|
||||
gh api repos/docker/docs/pulls/$ARGUMENTS/comments \
|
||||
--jq '[.[] | {id: .id, author: .user.login, body: .body, path: .path, line: .line}]'
|
||||
```
|
||||
|
||||
Always check both the reviews endpoint and the inline comments endpoint.
|
||||
A review with an empty body may still have line-level comments requiring
|
||||
action.
|
||||
|
||||
## 2. If merged
|
||||
|
||||
Report the final state. No further action needed.
|
||||
|
||||
## 3. If closed without merge
|
||||
|
||||
Read the closing context to understand why:
|
||||
|
||||
```bash
|
||||
gh pr view $ARGUMENTS --repo docker/docs --json closedAt,comments \
|
||||
--jq '{closedAt, lastComment: .comments[-1].body}'
|
||||
```
|
||||
|
||||
Report the reason. Common causes: rejected by maintainers, superseded by
|
||||
another PR, closed by automation.
|
||||
|
||||
## 4. If CI is failing
|
||||
|
||||
- Read the failure details (follow `detailsUrl` if needed)
|
||||
- Determine if the failure is in the PR's changed files or pre-existing
|
||||
- **Actionable:** check out the branch, fix, commit, push
|
||||
```bash
|
||||
git checkout <branch>
|
||||
# fix the issue
|
||||
git add <files>
|
||||
git commit -m "fix: <description>"
|
||||
git push
|
||||
```
|
||||
- **Pre-existing / upstream:** note it, do not block
|
||||
|
||||
## 5. If review comments or changes requested
|
||||
|
||||
- Read each unresolved comment
|
||||
- Address feedback in a follow-up commit
|
||||
- Push, then reply to each comment explaining what was done:
|
||||
```bash
|
||||
gh api repos/docker/docs/pulls/$ARGUMENTS/comments \
|
||||
--method POST \
|
||||
--field in_reply_to=<comment-id> \
|
||||
--field body="<response>"
|
||||
```
|
||||
- End every comment with a `Generated by [Claude Code](https://claude.com/claude-code)` footer
|
||||
- Re-request review if changes were requested
|
||||
|
||||
## 6. Report
|
||||
|
||||
```
|
||||
## PR #$ARGUMENTS: <title>
|
||||
|
||||
**State:** <open|merged|closed>
|
||||
**CI:** <passing|failing|pending>
|
||||
**Review:** <approved|changes requested|pending>
|
||||
**Action taken:** <what was done, or "none needed">
|
||||
```
|
||||
123
.agents/skills/create-pr/SKILL.md
Normal file
123
.agents/skills/create-pr/SKILL.md
Normal file
@@ -0,0 +1,123 @@
|
||||
---
|
||||
name: create-pr
|
||||
description: >
|
||||
Push the current branch and create a pull request against docker/docs.
|
||||
Use after changes are committed and reviewed. "create a PR", "submit the
|
||||
fix", "open a pull request for this".
|
||||
---
|
||||
|
||||
# Create PR
|
||||
|
||||
Push the branch and create a properly structured pull request.
|
||||
|
||||
## 1. Verify the branch
|
||||
|
||||
```bash
|
||||
git log --oneline main..HEAD # confirm commits exist
|
||||
git diff --quiet # confirm no unstaged changes
|
||||
```
|
||||
|
||||
## 2. Push the branch
|
||||
|
||||
Confirm origin points to your fork, not upstream:
|
||||
|
||||
```bash
|
||||
git remote get-url origin
|
||||
```
|
||||
|
||||
Then push:
|
||||
|
||||
```bash
|
||||
git push -u origin <branch-name>
|
||||
```
|
||||
|
||||
## 3. Create the PR
|
||||
|
||||
Derive the fork owner dynamically:
|
||||
|
||||
```bash
|
||||
FORK_OWNER=$(git remote get-url origin | sed -E 's|.*[:/]([^/]+)/[^/]+(\.git)?$|\1|')
|
||||
```
|
||||
|
||||
```bash
|
||||
gh pr create --repo docker/docs \
|
||||
--head "${FORK_OWNER}:<branch-name>" \
|
||||
--title "<concise summary under 70 chars>" \
|
||||
--body "$(cat <<'EOF'
|
||||
## Summary
|
||||
|
||||
<1-2 sentences: what was wrong and what was changed>
|
||||
|
||||
Closes #NNNN
|
||||
|
||||
Generated by [Claude Code](https://claude.com/claude-code)
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
Keep the body short. Reviewers need to know what changed and why — nothing
|
||||
else.
|
||||
|
||||
### Optional: Learnings section
|
||||
|
||||
If while working on this PR you discovered something non-obvious about the
|
||||
repo — a convention not documented in AGENTS.md, a gotcha that tripped you
|
||||
up, a pattern that should be codified — add a Learnings section to the PR
|
||||
body:
|
||||
|
||||
```markdown
|
||||
## Learnings
|
||||
|
||||
- <what you learned and why it matters>
|
||||
```
|
||||
|
||||
Add this section between the Summary and the `Closes` line. Only include
|
||||
learnings that would help future contributors avoid the same issue. Do not
|
||||
include things already documented in AGENTS.md or STYLE.md.
|
||||
|
||||
The weekly PR learnings scanner reads these sections to surface recurring
|
||||
patterns for the team to codify.
|
||||
|
||||
## 4. Apply labels and request review
|
||||
|
||||
Use the Issues API for labels — `gh pr edit --add-label` silently fails:
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/issues/<pr-number>/labels \
|
||||
--method POST \
|
||||
--field 'labels[]=status/review'
|
||||
```
|
||||
|
||||
Request review:
|
||||
|
||||
```bash
|
||||
gh pr edit <pr-number> --repo docker/docs --add-reviewer docker/docs-team
|
||||
```
|
||||
|
||||
Verify the reviewer was assigned:
|
||||
|
||||
```bash
|
||||
gh pr view <pr-number> --repo docker/docs --json reviewRequests \
|
||||
--jq '.reviewRequests[].slug'
|
||||
```
|
||||
|
||||
If the team doesn't appear, use the API directly:
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/pulls/<pr-number>/requested_reviewers \
|
||||
--method POST --field 'team_reviewers[]=docs-team'
|
||||
```
|
||||
|
||||
## 5. Report
|
||||
|
||||
Print the PR URL and current CI state:
|
||||
|
||||
```bash
|
||||
gh pr view <pr-number> --repo docker/docs --json url,state
|
||||
gh pr checks <pr-number> --repo docker/docs --json name,state
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Always use `Closes #NNNN` (not "Fixes") for GitHub auto-close linkage
|
||||
- One issue, one branch, one PR — never combine
|
||||
83
.agents/skills/fix-issue/SKILL.md
Normal file
83
.agents/skills/fix-issue/SKILL.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
name: fix-issue
|
||||
description: >
|
||||
Fix a single GitHub issue end-to-end: triage, research, write the fix,
|
||||
review, and create a PR. Use when asked to fix an issue: "fix issue 1234",
|
||||
"resolve #500", "create a PR for issue 200".
|
||||
argument-hint: "<issue-number>"
|
||||
---
|
||||
|
||||
# Fix Issue
|
||||
|
||||
Given GitHub issue **$ARGUMENTS**, decide what to do with it and either
|
||||
close it or fix it. This skill orchestrates the composable skills — it owns
|
||||
the decision tree, not the individual steps.
|
||||
|
||||
## 1. Triage
|
||||
|
||||
Invoke `/triage-issue $ARGUMENTS` to understand the issue and decide what
|
||||
to do. This runs in a forked subagent and returns a verdict.
|
||||
|
||||
## 2. Act on the triage result
|
||||
|
||||
If triage says **close it** — comment with the reason and close:
|
||||
```bash
|
||||
gh issue close $ARGUMENTS --repo docker/docs \
|
||||
--comment "<one sentence explaining why>
|
||||
|
||||
Generated by [Claude Code](https://claude.com/claude-code)"
|
||||
```
|
||||
Done.
|
||||
|
||||
If triage says **escalate upstream** — comment noting the repo and stop:
|
||||
```bash
|
||||
gh issue comment $ARGUMENTS --repo docker/docs \
|
||||
--body "This needs to be fixed in <upstream-repo>.
|
||||
|
||||
Generated by [Claude Code](https://claude.com/claude-code)"
|
||||
```
|
||||
Done.
|
||||
|
||||
If triage says **leave it open** — comment explaining what was checked and
|
||||
what's unclear. Do not close.
|
||||
Done.
|
||||
|
||||
End every issue comment with a `Generated by [Claude Code](https://claude.com/claude-code)` footer.
|
||||
|
||||
If triage says **fix it** — proceed to step 3.
|
||||
|
||||
## 3. Research
|
||||
|
||||
Invoke `/research` to locate affected files, verify facts, and identify
|
||||
the fix. The issue context carries over from triage. This runs inline —
|
||||
findings stay in conversation context for the write step.
|
||||
|
||||
If research reveals the issue is upstream or cannot be fixed (e.g.
|
||||
unverifiable URLs), comment on the issue and stop.
|
||||
|
||||
## 4. Write
|
||||
|
||||
Invoke `/write` to create a branch, make the change, format, self-review,
|
||||
and commit.
|
||||
|
||||
## 5. Review
|
||||
|
||||
Invoke `/review-changes` to check the diff for correctness, coherence, and
|
||||
mechanical compliance. This runs in a forked subagent with fresh context.
|
||||
|
||||
If issues are found, fix them and re-review until clean.
|
||||
|
||||
## 6. Create PR
|
||||
|
||||
Invoke `/create-pr` to push the branch and open a pull request.
|
||||
|
||||
## 7. Return to main
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
```
|
||||
|
||||
## 8. Report
|
||||
|
||||
Summarize what happened: the issue number, what was done (closed, escalated,
|
||||
fixed with a PR link), and why — in a sentence or two.
|
||||
93
.agents/skills/research/SKILL.md
Normal file
93
.agents/skills/research/SKILL.md
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
name: research
|
||||
description: >
|
||||
Research a documentation topic — locate affected files, understand the
|
||||
problem, identify what to change. Use when investigating an issue, a
|
||||
question, or a topic before writing a fix. Triggers on: "research issue
|
||||
1234", "investigate what needs changing for #500", "what files are
|
||||
affected by #200", "where is X documented", "is our docs page about Y
|
||||
accurate", "look into how we document Z".
|
||||
---
|
||||
|
||||
# Research
|
||||
|
||||
Thoroughly investigate the topic at hand and produce a clear plan for
|
||||
the fix. The goal is to identify exact files, named targets within those
|
||||
files, and the verified content needed for the fix.
|
||||
|
||||
## 1. Gather context
|
||||
|
||||
If the input is a GitHub issue number, fetch it:
|
||||
|
||||
```bash
|
||||
gh issue view <number> --repo docker/docs \
|
||||
--json number,title,body,labels,comments
|
||||
```
|
||||
|
||||
Otherwise, work from what was provided — a description, a URL, a question,
|
||||
or prior conversation context. Identify the topic, affected feature, or
|
||||
page to investigate.
|
||||
|
||||
## 2. Locate affected files
|
||||
|
||||
Search `content/` using the URL or topic from the issue. Remember the
|
||||
`/manuals` prefix mapping when converting URLs to file paths.
|
||||
|
||||
For each candidate file, read the relevant section to confirm it contains
|
||||
the reported problem.
|
||||
|
||||
## 3. Check vendored ownership
|
||||
|
||||
Before planning any edit, verify the file is editable locally:
|
||||
|
||||
- `_vendor/` — read-only, vendored via Hugo modules
|
||||
- `data/cli/` — read-only, generated from upstream YAML
|
||||
- `content/reference/cli/` — read-only, generated from `data/cli/`
|
||||
- Everything else in `content/` — editable
|
||||
|
||||
If the fix requires upstream changes, identify the upstream repo and note
|
||||
it as out of scope. See the vendored content table in CLAUDE.md.
|
||||
|
||||
## 4. Find related content
|
||||
|
||||
Look for pages that may need updating alongside the primary fix:
|
||||
|
||||
- Pages that link to the affected content
|
||||
- Include files (`content/includes/`) referenced by the page
|
||||
- Related pages in the same section describing the same feature
|
||||
|
||||
## 5. Verify facts
|
||||
|
||||
If the issue makes a factual claim about how a feature behaves, verify it.
|
||||
Follow external links, read upstream source, check release notes. Do not
|
||||
plan a fix based on an unverified claim.
|
||||
|
||||
If the fix requires a replacement URL and that URL cannot be verified (e.g.
|
||||
network restrictions), report it as a blocker rather than guessing.
|
||||
|
||||
## 6. Check the live site (if needed)
|
||||
|
||||
For URL or rendering issues, fetch the live page:
|
||||
|
||||
```
|
||||
https://docs.docker.com/<path>/
|
||||
```
|
||||
|
||||
## 7. Report findings
|
||||
|
||||
Summarize what you found — files to change, the specific problem in each,
|
||||
what the fix should be, and any constraints. This context feeds directly
|
||||
into the write step.
|
||||
|
||||
Be specific: name the file, the section or element within it, and the
|
||||
verified content needed. "Fix the broken link in networking.md" is not
|
||||
specific enough. "In `compose/networking.md`, the 'Custom networks' section,
|
||||
remove the note about `driver_opts` being ignored — this was fixed in
|
||||
Compose 2.24" is.
|
||||
|
||||
## Notes
|
||||
|
||||
- Research quality bounds write quality. Vague research produces broad
|
||||
changes; precise research produces minimal ones.
|
||||
- Do not create standalone research files — findings stay in conversation
|
||||
context for the write step.
|
||||
107
.agents/skills/review-changes/SKILL.md
Normal file
107
.agents/skills/review-changes/SKILL.md
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
name: review-changes
|
||||
description: >
|
||||
Review uncommitted or recently committed documentation changes for
|
||||
correctness, coherence, and style compliance. Use before creating a PR
|
||||
to catch issues. "review my changes", "review the diff", "check the fix
|
||||
before submitting", "does this look right".
|
||||
context: fork
|
||||
model: opus
|
||||
---
|
||||
|
||||
# Review Changes
|
||||
|
||||
Evaluate whether the changes correctly and completely solve the stated
|
||||
problem, without introducing new issues. Start with no assumptions — the
|
||||
change may contain mistakes. Your job is to catch what the writer missed,
|
||||
not to rubber-stamp the diff.
|
||||
|
||||
## 1. Identify what changed
|
||||
|
||||
Determine the scope of changes to review:
|
||||
|
||||
```bash
|
||||
# Uncommitted changes
|
||||
git diff --name-only
|
||||
|
||||
# Last commit
|
||||
git diff --name-only HEAD~1
|
||||
|
||||
# Entire branch vs main
|
||||
git diff --name-only main...HEAD
|
||||
```
|
||||
|
||||
Pick the right comparison for what's being reviewed. If reviewing a branch,
|
||||
use `main...HEAD` to see all changes since the branch diverged.
|
||||
|
||||
## 2. Read each changed file in full
|
||||
|
||||
Do not just read the diff. For every changed file, read the entire file to
|
||||
understand the full context the change lives in. A diff can look correct in
|
||||
isolation but contradict something earlier on the same page.
|
||||
|
||||
Then read the diff for the detailed changes:
|
||||
|
||||
```bash
|
||||
# Adjust the comparison to match step 1
|
||||
git diff --unified=10 # uncommitted
|
||||
git diff --unified=10 HEAD~1 # last commit
|
||||
git diff --unified=10 main...HEAD # branch
|
||||
```
|
||||
|
||||
## 3. Follow cross-references
|
||||
|
||||
For each changed file, check what links to it and what it links to:
|
||||
|
||||
- Search for other pages that reference the changed content (grep for the
|
||||
filename, heading anchors, or key phrases)
|
||||
- Read linked pages to verify the change doesn't create contradictions
|
||||
across pages
|
||||
- Check that anchor links in cross-references still match heading IDs
|
||||
|
||||
A change that's correct on its own page can break the story told by a
|
||||
related page.
|
||||
|
||||
## 4. Verify factual accuracy
|
||||
|
||||
Don't assume the change is factually correct just because it reads well.
|
||||
|
||||
- If the change describes how a feature behaves, verify against upstream
|
||||
docs or source code
|
||||
- If the change includes a URL, check that it resolves
|
||||
- If the change references a CLI flag, option, or API field, confirm it
|
||||
exists
|
||||
|
||||
## 5. Evaluate as a reader
|
||||
|
||||
Consider someone landing on this page from a search result, with no prior
|
||||
context:
|
||||
|
||||
- Does the page make sense on its own?
|
||||
- Is the changed section clear without having read the issue or diff?
|
||||
- Would a reader be confused by anything the change introduces or leaves
|
||||
out?
|
||||
|
||||
## 6. Review code and template changes
|
||||
|
||||
For non-Markdown changes (JS, HTML, CSS, Hugo templates):
|
||||
|
||||
- Trace through the common execution path
|
||||
- Trace through at least one edge case (no stored preference, Alpine fails
|
||||
to load, first visit vs returning visitor)
|
||||
- Ask whether the change could produce unexpected browser or runtime
|
||||
behavior that no automated tool would catch
|
||||
|
||||
## 7. Decision
|
||||
|
||||
**Approve** if the change is correct, coherent, complete, and factually
|
||||
accurate.
|
||||
|
||||
**Request changes** if:
|
||||
- The change does not correctly solve the stated problem
|
||||
- There is a factual error or contradiction (on-page or cross-page)
|
||||
- A cross-reference is broken or misleading
|
||||
- A reader would be confused
|
||||
|
||||
When requesting changes, be specific: quote the exact text that is wrong,
|
||||
explain why, and suggest the correct fix.
|
||||
136
.agents/skills/triage-issue/SKILL.md
Normal file
136
.agents/skills/triage-issue/SKILL.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
name: triage-issue
|
||||
description: >
|
||||
Analyze a single GitHub issue for docker/docs — check whether the problem
|
||||
still exists, determine a verdict, and report findings. Use when asked to
|
||||
triage, assess, or review an issue, even if the user doesn't say "triage"
|
||||
explicitly: "triage issue 1234", "is issue 500 still valid", "should we
|
||||
close #200", "look at this issue", "what's going on with #200".
|
||||
argument-hint: "<issue-number>"
|
||||
context: fork
|
||||
---
|
||||
|
||||
# Triage Issue
|
||||
|
||||
Given GitHub issue **$ARGUMENTS** from docker/docs, figure out whether
|
||||
it's still a real problem and say what should happen next.
|
||||
|
||||
## 1. Fetch the issue
|
||||
|
||||
```bash
|
||||
gh issue view $ARGUMENTS --repo docker/docs \
|
||||
--json number,title,body,state,labels,createdAt,updatedAt,closedAt,assignees,author,comments
|
||||
```
|
||||
|
||||
## 2. Understand the problem
|
||||
|
||||
Read the issue body and all comments. Identify:
|
||||
|
||||
- What is the reported problem?
|
||||
- What content, URL, or file does it reference?
|
||||
- Are there linked PRs? Check whether they were merged or closed without merge.
|
||||
- Has anyone already proposed a fix or workaround in the comments?
|
||||
|
||||
## 3. Follow URLs
|
||||
|
||||
Find all `docs.docker.com` URLs in the issue body and comments. For each:
|
||||
|
||||
- Fetch the URL to check if it still exists (404 = content removed or moved)
|
||||
- Check whether the content still contains the problem described
|
||||
- Note when the page was last updated relative to when the issue was filed
|
||||
|
||||
For non-docs URLs (GitHub links, external references), fetch them too if
|
||||
they are central to understanding the issue.
|
||||
|
||||
## 4. Check the repository
|
||||
|
||||
If the issue references specific files, content sections, or code:
|
||||
|
||||
- Find and read the current version of that content
|
||||
- Check whether the problem has been fixed, content moved, or file removed
|
||||
- Remember the `/manuals` prefix mapping when looking up files
|
||||
|
||||
## 5. Check for upstream ownership
|
||||
|
||||
If the issue is about content in `_vendor/` or `data/cli/`, it cannot be
|
||||
fixed here. Identify which upstream repo owns it (see the vendored content
|
||||
table in CLAUDE.md).
|
||||
|
||||
## 6. Decide and act
|
||||
|
||||
After investigating, pick one of these verdicts and take the corresponding
|
||||
action on the issue:
|
||||
|
||||
- **Close it** — the problem is already fixed, the content no longer exists,
|
||||
or the issue is too outdated to be useful. Close the issue with a comment
|
||||
explaining why:
|
||||
|
||||
```bash
|
||||
gh issue close $ARGUMENTS --repo docker/docs \
|
||||
--comment "Closing: <one-sentence reason>"
|
||||
```
|
||||
|
||||
- **Fix it** — the problem is real and fixable in this repo. Name the
|
||||
file(s) and what needs to change. Label the issue `status/confirmed` and
|
||||
remove `status/triage` if present:
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels \
|
||||
--method POST --field 'labels[]=status/confirmed'
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels/status%2Ftriage \
|
||||
--method DELETE || true
|
||||
```
|
||||
|
||||
- **Escalate upstream** — the problem is real but lives in vendored content.
|
||||
Name the upstream repo. Label the issue `status/upstream` and remove
|
||||
`status/triage` if present:
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels \
|
||||
--method POST --field 'labels[]=status/upstream'
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels/status%2Ftriage \
|
||||
--method DELETE || true
|
||||
```
|
||||
|
||||
- **Leave it open** — you can't determine the current state, or the issue
|
||||
needs human judgment. Label the issue `status/needs-analysis`:
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels \
|
||||
--method POST --field 'labels[]=status/needs-analysis'
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels/status%2Ftriage \
|
||||
--method DELETE || true
|
||||
```
|
||||
|
||||
Don't overthink the classification. An old issue isn't stale if the problem
|
||||
still exists. An upstream issue is still valid — it's just not fixable here.
|
||||
|
||||
Also apply the most relevant `area/` label based on the content affected.
|
||||
Available area labels: `area/accounts`, `area/admin`, `area/ai`,
|
||||
`area/api`, `area/billing`, `area/build`, `area/build-cloud`, `area/cli`,
|
||||
`area/compose`, `area/compose-spec`, `area/config`, `area/contrib`,
|
||||
`area/copilot`, `area/desktop`, `area/dhi`, `area/engine`,
|
||||
`area/enterprise`, `area/extensions`, `area/get-started`, `area/guides`,
|
||||
`area/hub`, `area/install`, `area/networking`, `area/offload`,
|
||||
`area/release-notes`, `area/samples`, `area/scout`, `area/security`,
|
||||
`area/storage`, `area/subscription`, `area/swarm`, `area/ux`. Pick one
|
||||
(or at most two if the issue clearly spans areas). Skip if none fit.
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/issues/$ARGUMENTS/labels \
|
||||
--method POST --field 'labels[]=area/<name>'
|
||||
```
|
||||
|
||||
## 7. Report
|
||||
|
||||
Write a short summary: what the issue reports, what you found, and what
|
||||
should happen next. Reference the specific files, URLs, or PRs that support
|
||||
your conclusion. Skip metadata fields — the issue itself has the dates and
|
||||
labels. Mention the action you took (closed, labeled, etc.).
|
||||
|
||||
## Notes
|
||||
|
||||
- A merged PR linked to an issue is strong evidence the issue is fixed
|
||||
- A closed-without-merge PR means the issue is likely still open
|
||||
- Do not narrate your process — produce the final report
|
||||
- End every issue comment with a `Generated by [Claude Code](https://claude.com/claude-code)` footer
|
||||
87
.agents/skills/write/SKILL.md
Normal file
87
.agents/skills/write/SKILL.md
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
name: write
|
||||
description: >
|
||||
Write a documentation fix on a branch. Makes the minimal change, formats,
|
||||
self-reviews, and commits. Use after research has identified what to change.
|
||||
"write the fix", "make the changes", "implement the fix for #1234".
|
||||
hooks:
|
||||
PostToolUse:
|
||||
- matcher: "Edit|Write"
|
||||
hooks:
|
||||
- type: command
|
||||
command: "bash ${CLAUDE_SKILL_DIR}/scripts/post-edit.sh"
|
||||
---
|
||||
|
||||
# Write
|
||||
|
||||
Make the minimal change that resolves the issue. Research has already
|
||||
identified what to change — this skill handles the edit, formatting,
|
||||
self-review, and commit.
|
||||
|
||||
## 1. Create a branch
|
||||
|
||||
```bash
|
||||
git checkout -b fix/issue-<number>-<short-desc> main
|
||||
```
|
||||
|
||||
Use a short kebab-case description derived from the issue title (3-5 words).
|
||||
|
||||
## 2. Read then edit
|
||||
|
||||
Always read each file before modifying it. Make the minimal change that
|
||||
fixes the issue. Do not improve surrounding content, add comments, or
|
||||
address adjacent problems.
|
||||
|
||||
Follow the writing guidelines in CLAUDE.md, STYLE.md, and COMPONENTS.md.
|
||||
|
||||
## 3. Front matter check
|
||||
|
||||
Every content page requires `title`, `description`, and `keywords` in its
|
||||
front matter. If any are missing from a file you touch, add them.
|
||||
|
||||
## 4. Validate
|
||||
|
||||
Prettier runs automatically after each edit via the PostToolUse hook.
|
||||
Run lint manually after all edits are complete:
|
||||
|
||||
```bash
|
||||
${CLAUDE_SKILL_DIR}/scripts/lint.sh <changed-files>
|
||||
```
|
||||
|
||||
The lint script runs markdownlint and vale on only the files you pass it,
|
||||
so the output is scoped to your changes. Fix any errors it reports.
|
||||
|
||||
## 5. Self-review
|
||||
|
||||
Re-read each changed file: right file, right lines, change is complete,
|
||||
front matter is present. Run `git diff` and verify only intended changes
|
||||
are present.
|
||||
|
||||
## 6. Commit
|
||||
|
||||
Stage only the changed files:
|
||||
|
||||
```bash
|
||||
git add <files>
|
||||
git diff --cached --name-only # verify — no package-lock.json or other noise
|
||||
git commit -m "$(cat <<'EOF'
|
||||
docs: <short description under 72 chars> (fixes #NNNN)
|
||||
|
||||
<What was wrong: one sentence citing the specific problem.>
|
||||
<What was changed: one sentence describing the exact edit.>
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
The commit body is mandatory. A reviewer reading only the commit should
|
||||
understand the problem and the fix without opening the issue.
|
||||
|
||||
## Notes
|
||||
|
||||
- Never edit `_vendor/` or `data/cli/` — these are vendored
|
||||
- If a file doesn't exist, check for renames:
|
||||
`git log --all --full-history -- "**/filename.md"`
|
||||
- If the fix requires a URL that cannot be verified, stop and report a
|
||||
blocker rather than guessing
|
||||
27
.agents/skills/write/scripts/lint.sh
Executable file
27
.agents/skills/write/scripts/lint.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Run markdownlint and vale on specific files.
|
||||
# Usage: .agents/skills/write/scripts/lint.sh <file> [file...]
|
||||
#
|
||||
# Designed for agent workflows — scoped output, no repo-wide noise.
|
||||
# For full repo validation, use: docker buildx bake validate
|
||||
set -uo pipefail
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Usage: $0 <file> [file...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit_code=0
|
||||
|
||||
echo "=== markdownlint ==="
|
||||
if ! npx markdownlint-cli "$@" 2>&1; then
|
||||
exit_code=1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== vale ==="
|
||||
if ! vale "$@" 2>&1; then
|
||||
exit_code=1
|
||||
fi
|
||||
|
||||
exit $exit_code
|
||||
12
.agents/skills/write/scripts/post-edit.sh
Executable file
12
.agents/skills/write/scripts/post-edit.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
# PostToolUse hook for Edit/Write in the write skill.
|
||||
# Auto-formats Markdown files with prettier after each edit.
|
||||
set -euo pipefail
|
||||
|
||||
input=$(cat)
|
||||
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
||||
|
||||
[ -z "$file_path" ] && exit 0
|
||||
[[ "$file_path" != *.md ]] && exit 0
|
||||
|
||||
npx prettier --write "$file_path" 2>/dev/null
|
||||
@@ -1,127 +0,0 @@
|
||||
---
|
||||
name: fix-issues
|
||||
description: >
|
||||
Fix one or more GitHub issues by creating branches, writing fixes, and opening PRs.
|
||||
Use this skill whenever the user provides GitHub issue numbers and wants them fixed,
|
||||
or says things like "fix issue 1234", "address these issues", "create PRs for issues
|
||||
1234 and 5678". Triggers on any request involving GitHub issue numbers paired with
|
||||
fixing, addressing, resolving, or creating PRs. Also triggers for "fix #1234" shorthand.
|
||||
---
|
||||
|
||||
# Fix Issues
|
||||
|
||||
Given one or more GitHub issue numbers from the docker/docs repository, fix each
|
||||
issue end-to-end: analyze, branch, fix, commit, push, and open a PR.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Fetch all issues in parallel
|
||||
|
||||
Use `gh issue view <number> --repo docker/docs --json title,body,labels` for each
|
||||
issue number. Launch all fetches in parallel since they're independent.
|
||||
|
||||
### 2. Fix each issue sequentially
|
||||
|
||||
Process each issue one at a time in the main context. Do NOT use background
|
||||
subagents for this — they can't get interactive Bash permission approval, which
|
||||
blocks all git operations. Sequential processing in the main context is faster
|
||||
than agents that stall on permissions.
|
||||
|
||||
For each issue:
|
||||
|
||||
#### a. Analyze
|
||||
|
||||
Read the issue body to understand:
|
||||
- Which file(s) need changes
|
||||
- What the problem is
|
||||
- What the fix should be
|
||||
|
||||
#### b. Create a branch
|
||||
|
||||
```bash
|
||||
git checkout -b fix/issue-<number>-<short-description> main
|
||||
```
|
||||
|
||||
Use a short kebab-case description derived from the issue title (3-5 words max).
|
||||
|
||||
#### c. Read and fix
|
||||
|
||||
- Read each affected file before editing
|
||||
- Make the minimal change that addresses the issue
|
||||
- Don't over-engineer or add unrequested improvements
|
||||
- Follow the repository's STYLE.md and COMPONENTS.md guidelines
|
||||
|
||||
#### d. Format
|
||||
|
||||
Run prettier on every changed file:
|
||||
|
||||
```bash
|
||||
npx prettier --write <file>
|
||||
```
|
||||
|
||||
#### e. Self-review
|
||||
|
||||
Re-read the changed file to verify:
|
||||
- The fix addresses the issue correctly
|
||||
- No unintended changes were introduced
|
||||
- Formatting looks correct
|
||||
|
||||
#### f. Commit
|
||||
|
||||
Stage only the changed files (not `git add -A`).
|
||||
|
||||
#### g. Push and create PR
|
||||
|
||||
```bash
|
||||
git push -u origin fix/issue-<number>-<short-description>
|
||||
```
|
||||
|
||||
Then create the PR:
|
||||
|
||||
```bash
|
||||
gh pr create --repo docker/docs \
|
||||
--title "<Short summary matching commit>" \
|
||||
--body "$(cat <<'EOF'
|
||||
## Summary
|
||||
|
||||
- <1-3 bullet points describing what changed and why>
|
||||
|
||||
Closes #<issue-number>
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
#### h. Label and assign reviewers
|
||||
|
||||
```bash
|
||||
gh pr edit <pr-number> --repo docker/docs \
|
||||
--add-label "status/review" \
|
||||
--add-reviewer docker/docs-team
|
||||
```
|
||||
|
||||
### 3. Switch back to main
|
||||
|
||||
After all issues are processed:
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
```
|
||||
|
||||
### 4. Report results
|
||||
|
||||
Present a summary table:
|
||||
|
||||
| Issue | PR | Change |
|
||||
|-------|-----|--------|
|
||||
| #N | #M | Brief description |
|
||||
|
||||
## Important notes
|
||||
|
||||
- Always work from `main` as the base for each branch
|
||||
- Each issue gets its own branch and PR — don't combine issues
|
||||
- If an issue references a file that doesn't exist, check for renames or
|
||||
reorganization before giving up (files move around in this repo)
|
||||
- Validation commands (`docker buildx bake lint vale`) are available but slow;
|
||||
only run them if the user asks or the changes are complex enough to warrant it
|
||||
@@ -1,150 +0,0 @@
|
||||
---
|
||||
name: process-issues
|
||||
description: >
|
||||
Process a batch of GitHub issues end-to-end: fetch unlabeled issues, triage
|
||||
them, apply labels, fix the actionable ones, and babysit the resulting PRs.
|
||||
Use this skill when the user wants to work through the issue backlog
|
||||
autonomously — e.g. "process issues", "work through the backlog", "run the
|
||||
issue pipeline". Accepts an optional batch size: "process issues 5".
|
||||
Pairs well with /loop for continuous background processing.
|
||||
---
|
||||
|
||||
# Process Issues
|
||||
|
||||
Fetches a batch of unprocessed GitHub issues, triages each one, labels it,
|
||||
fixes the actionable ones, and babysits the resulting PRs.
|
||||
|
||||
## Arguments
|
||||
|
||||
- Batch size (optional, default 10): number of issues to process per run.
|
||||
E.g. "process issues 5" or "process issues --batch 5".
|
||||
|
||||
## Labels
|
||||
|
||||
These labels track agent processing state. Create any that don't exist yet
|
||||
with `gh label create --repo docker/docs <name> --color <hex>`.
|
||||
|
||||
| Label | Meaning |
|
||||
|-------|---------|
|
||||
| `agent/triaged` | Agent has analyzed this issue; verdict in a comment |
|
||||
| `agent/fix` | Agent has opened a PR for this issue |
|
||||
| `agent/skip` | Triaged; not actionable (STALE, UPSTREAM, INDETERMINATE, CLOSEABLE_FIXED) |
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Resolve fork username and fetch a batch
|
||||
|
||||
Get the authenticated user's GitHub login — don't hardcode it:
|
||||
|
||||
```bash
|
||||
FORK_USER=$(gh api user --jq '.login')
|
||||
```
|
||||
|
||||
Fetch up to N open issues that have none of the `agent/*` labels:
|
||||
|
||||
```bash
|
||||
gh issue list --repo docker/docs \
|
||||
--state open \
|
||||
--limit <N> \
|
||||
--json number,title,labels \
|
||||
--jq '[.[] | select(
|
||||
([.labels[].name] | map(startswith("agent/")) | any) | not
|
||||
)]'
|
||||
```
|
||||
|
||||
If there are no unprocessed issues, report that the backlog is clear and stop.
|
||||
|
||||
### 2. Triage each issue
|
||||
|
||||
Follow the full **triage-issues** skill workflow for all fetched issues,
|
||||
running fetches in parallel. Produce a verdict for each:
|
||||
OPEN, CLOSEABLE_FIXED, UPSTREAM, INDETERMINATE, or STALE.
|
||||
|
||||
### 3. Label each issue immediately after verdict
|
||||
|
||||
Apply `agent/triaged` to every issue regardless of verdict — it means "we
|
||||
looked at it." Then apply a second label based on the outcome:
|
||||
|
||||
```bash
|
||||
# All issues — mark as triaged
|
||||
gh issue edit <number> --repo docker/docs --add-label "agent/triaged"
|
||||
|
||||
# Non-actionable (STALE, UPSTREAM, INDETERMINATE)
|
||||
gh issue edit <number> --repo docker/docs --add-label "agent/skip"
|
||||
|
||||
# Already resolved (CLOSEABLE_FIXED) — close with explanation
|
||||
gh issue close <number> --repo docker/docs \
|
||||
--comment "Closing — <one sentence explaining what resolved it>."
|
||||
|
||||
# Actionable (OPEN, no existing PR) — no extra label yet; agent/fix applied after PR is created
|
||||
```
|
||||
|
||||
Leave a comment on every issue summarising the verdict and reasoning in one
|
||||
sentence. Do this immediately — don't batch it for the end.
|
||||
|
||||
### 4. Fix actionable issues
|
||||
|
||||
For each issue with verdict OPEN and no existing open PR, follow the
|
||||
**fix-issues** skill workflow.
|
||||
|
||||
Skip issues where:
|
||||
- An open PR already exists
|
||||
- Verdict is anything other than OPEN
|
||||
- The fix requires changes to `_vendor/` or `data/cli/` (upstream owned)
|
||||
|
||||
After the PR is created, apply `agent/fix` to the issue:
|
||||
|
||||
```bash
|
||||
gh issue edit <number> --repo docker/docs --add-label "agent/fix"
|
||||
```
|
||||
|
||||
### 5. Babysit PRs
|
||||
|
||||
After opening PRs, schedule a recurring check with `/loop` so babysitting
|
||||
continues asynchronously after the batch summary is reported:
|
||||
|
||||
```
|
||||
/loop 5m babysit PRs <#N, #M, …> in docker/docs — check for failing checks,
|
||||
new review comments, and requested changes; investigate and fix anything that
|
||||
needs attention; stop looping once all PRs are merged or closed
|
||||
```
|
||||
|
||||
At each check, for every open PR:
|
||||
|
||||
- **Failing checks**: investigate the failure, fix the cause, force-push an
|
||||
updated commit to the branch via the GitHub API
|
||||
- **Review comments**: read them, address the feedback, push an update, reply
|
||||
to the comment
|
||||
- **All clear**: note it and move on
|
||||
|
||||
Don't just report status — act on anything that needs attention.
|
||||
|
||||
### 6. Report results
|
||||
|
||||
```
|
||||
## Batch summary
|
||||
|
||||
Processed: <N> issues
|
||||
PRs opened: <n>
|
||||
Skipped: <n> (STALE: n, UPSTREAM: n, INDETERMINATE: n)
|
||||
Closed: <n> (already resolved)
|
||||
|
||||
### PRs opened
|
||||
| Issue | PR | Checks | Review |
|
||||
|-------|-----|--------|--------|
|
||||
| #N | #M | ✅ | pending |
|
||||
|
||||
### Skipped
|
||||
| Issue | Verdict | Reason |
|
||||
|-------|---------|--------|
|
||||
| #N | STALE | ... |
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- **Fork username**: always resolve dynamically with `gh api user --jq '.login'`
|
||||
- **One issue, one PR**: never combine multiple issues in a single branch
|
||||
- **Validation**: skip `docker buildx bake lint vale` unless the change is
|
||||
complex — it's slow and the basic checks run automatically on the PR
|
||||
- **Resumability**: labels are applied immediately at triage time, so if the
|
||||
session ends mid-run the next run skips already-processed issues automatically
|
||||
@@ -1,135 +0,0 @@
|
||||
---
|
||||
name: triage-issues
|
||||
description: >
|
||||
Triage one or more GitHub issues for the docker/docs repository. Analyzes each
|
||||
issue's content, checks whether the problem still exists in the repo and on the
|
||||
live site, and produces a structured verdict. Use this skill whenever the user
|
||||
asks to triage, analyze, review, or assess GitHub issues — e.g. "triage issue
|
||||
1234", "what's the status of these issues", "which of these can be closed",
|
||||
"look at issues 100 200 300 and tell me what to do with them".
|
||||
---
|
||||
|
||||
# Triage Issues
|
||||
|
||||
Given one or more GitHub issue numbers from the docker/docs repository, analyze
|
||||
each issue and produce a structured verdict on its current status.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Fetch all issues in parallel
|
||||
|
||||
For each issue number, fetch everything in a single call:
|
||||
|
||||
```bash
|
||||
gh issue view <number> --repo docker/docs \
|
||||
--json number,title,body,state,labels,createdAt,updatedAt,closedAt,assignees,author,comments
|
||||
```
|
||||
|
||||
When triaging multiple issues, fetch all of them in parallel before starting
|
||||
analysis — don't process one at a time.
|
||||
|
||||
### 2. Analyze each issue
|
||||
|
||||
For each issue, work through these checks:
|
||||
|
||||
#### a. Understand the problem
|
||||
|
||||
Read the issue body and all comments. Identify:
|
||||
- What is the reported problem?
|
||||
- What content, URL, or file does it reference?
|
||||
- Are there linked PRs? Check whether they were merged or closed without merge.
|
||||
- Has anyone already proposed a fix or workaround in the comments?
|
||||
|
||||
#### b. Follow URLs
|
||||
|
||||
Find all `docs.docker.com` URLs in the issue body and comments. For each one:
|
||||
- Fetch the URL to check if it still exists (404 = content removed or moved)
|
||||
- Check whether the content still contains the problem described
|
||||
- Note when the page was last updated relative to when the issue was filed
|
||||
|
||||
For non-docs URLs (GitHub links, external references), fetch them too if they
|
||||
are central to understanding the issue.
|
||||
|
||||
#### c. Check the repository
|
||||
|
||||
If the issue references specific files, content sections, or code:
|
||||
- Use file tools to find and read the current version of that content
|
||||
- Check whether the problem has been fixed, the content moved, or the file removed
|
||||
- Remember the `/manuals` prefix mapping when looking up files
|
||||
|
||||
#### d. Check for upstream ownership
|
||||
|
||||
If the issue is about content in `_vendor/` or `data/cli/`, it cannot be fixed
|
||||
here. Identify which upstream repo owns it and note that in your analysis.
|
||||
|
||||
### 3. Determine verdict
|
||||
|
||||
Assign one of these verdicts based on what you found:
|
||||
|
||||
| Verdict | When to use |
|
||||
|---------|-------------|
|
||||
| **OPEN** | Issue is valid and still unfixed in this repo |
|
||||
| **CLOSEABLE_FIXED** | Content has been updated, corrected, or removed since the issue was filed |
|
||||
| **UPSTREAM** | Problem exists but originates in vendored/upstream content |
|
||||
| **INDETERMINATE** | Not enough information to determine current state |
|
||||
| **STALE** | Outdated with no recent activity; references content or features that no longer exist; context has changed enough that a new issue would be more appropriate |
|
||||
|
||||
Be confident when evidence is clear. Use INDETERMINATE only when you genuinely
|
||||
cannot determine the current state after checking.
|
||||
|
||||
### 4. Report results
|
||||
|
||||
#### Single issue
|
||||
|
||||
Print a structured report:
|
||||
|
||||
```
|
||||
## Issue #<number>: <title>
|
||||
|
||||
**Verdict:** <VERDICT>
|
||||
**Confidence:** <high|medium|low>
|
||||
**Filed:** <creation date>
|
||||
**Last activity:** <last comment or update date>
|
||||
**Labels:** <labels or "none">
|
||||
|
||||
### Summary
|
||||
<One or two sentences describing the reported problem.>
|
||||
|
||||
### Analysis
|
||||
<What you checked and what you found. Reference specific URLs, files, or
|
||||
content. Note any linked PRs or related issues.>
|
||||
|
||||
### Recommendation
|
||||
<Concrete next step: close with a comment, fix specific content, escalate
|
||||
to upstream repo, request more info from reporter, etc.>
|
||||
```
|
||||
|
||||
#### Multiple issues
|
||||
|
||||
Start with a summary table, then print the full report for each issue:
|
||||
|
||||
```
|
||||
| Issue | Title | Verdict | Confidence |
|
||||
|-------|-------|---------|------------|
|
||||
| #123 | ... | OPEN | high |
|
||||
| #456 | ... | STALE | medium |
|
||||
|
||||
---
|
||||
|
||||
## Issue #123: ...
|
||||
[full report]
|
||||
|
||||
---
|
||||
|
||||
## Issue #456: ...
|
||||
[full report]
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- A merged PR linked to an issue is strong evidence the issue is fixed
|
||||
- A closed-without-merge PR means the issue is likely still open
|
||||
- Check creation date and last activity to assess staleness — issues with no
|
||||
activity in over a year that reference old product versions are candidates
|
||||
for STALE
|
||||
- Do not narrate your process; just produce the final report(s)
|
||||
211
AGENTS.md
211
AGENTS.md
@@ -1,7 +1,7 @@
|
||||
# AGENTS.md
|
||||
|
||||
Instructions for AI agents working on the Docker documentation
|
||||
repository. This site builds https://docs.docker.com/ using Hugo.
|
||||
Instructions for AI agents working on Docker documentation.
|
||||
This site builds https://docs.docker.com/ using Hugo.
|
||||
|
||||
## Project structure
|
||||
|
||||
@@ -18,27 +18,94 @@ static/ # Images, fonts
|
||||
_vendor/ # Vendored Hugo modules (read-only)
|
||||
```
|
||||
|
||||
## URL prefix stripping
|
||||
|
||||
The `/manuals` prefix is stripped from published URLs:
|
||||
`content/manuals/desktop/` → `/desktop/` on the live site.
|
||||
`content/manuals/desktop/install.md` becomes `/desktop/install/` on the live
|
||||
site.
|
||||
|
||||
When writing internal cross-references in source files, keep the `/manuals/`
|
||||
prefix in the path — Hugo requires the full source path. The stripping only
|
||||
affects the published URL, not the internal link target. Anchor links must
|
||||
exactly match the generated heading ID (Hugo lowercases and slugifies
|
||||
headings).
|
||||
|
||||
## Vendored content (do not edit)
|
||||
|
||||
Content in `_vendor/` and CLI reference data in `data/cli/` are vendored
|
||||
from upstream repos. Content pages under `content/reference/cli/` are
|
||||
generated from `data/cli/` YAML. Do not edit any of these files — changes
|
||||
must go to the source repository:
|
||||
|
||||
| Content | Source repo |
|
||||
|---------|-------------|
|
||||
| CLI reference (`docker`, `docker build`, etc.) | docker/cli |
|
||||
| Buildx reference | docker/buildx |
|
||||
| Compose reference | docker/compose |
|
||||
| Model Runner reference | docker/model-runner |
|
||||
| Dockerfile reference | moby/buildkit |
|
||||
| Engine API reference | moby/moby |
|
||||
|
||||
If a validation failure or broken link traces back to vendored content, note
|
||||
the upstream repo that needs fixing. Do not attempt to fix it locally.
|
||||
|
||||
## Writing guidelines
|
||||
|
||||
Read and follow [STYLE.md](STYLE.md) and [COMPONENTS.md](COMPONENTS.md).
|
||||
These contain all style rules, shortcode syntax, and front matter
|
||||
requirements.
|
||||
These contain all style rules, shortcode syntax, and front matter requirements.
|
||||
|
||||
## Vendored content (do not edit)
|
||||
### Style violations to avoid
|
||||
|
||||
Content in `_vendor/` and CLI reference pages generated from
|
||||
`data/cli/` are vendored from upstream repos. Don't edit these
|
||||
files — changes must go to the source repository:
|
||||
Every piece of writing must avoid these words and patterns (enforced by Vale):
|
||||
|
||||
- docker/cli, docker/buildx, docker/compose, docker/model-runner → CLI reference YAML in `data/cli/`
|
||||
- moby/buildkit → Dockerfile reference in `_vendor/`
|
||||
- moby/moby → Engine API docs in `_vendor/`
|
||||
- Hedge words: "simply", "easily", "just", "seamlessly"
|
||||
- Meta-commentary: "it's worth noting", "it's important to understand"
|
||||
- "allows you to" or "enables you to" — use "lets you" or rephrase
|
||||
- "we" — use "you" or "Docker"
|
||||
- "click" — use "select"
|
||||
- Bold for emphasis or product names — only bold UI elements
|
||||
- Time-relative language: "currently", "new", "recently", "now"
|
||||
|
||||
If a validation failure traces back to vendored content, note the
|
||||
upstream repo that needs fixing but don't block on it.
|
||||
### Version-introduction notes
|
||||
|
||||
Explicit version anchors ("Starting with Docker Desktop version X...") are
|
||||
different from time-relative language — they mark when a feature was
|
||||
introduced, which is permanently true.
|
||||
|
||||
- Recent releases (~6 months): leave version callouts in place
|
||||
- Old releases: consider removing if the callout adds little value
|
||||
- When in doubt, keep the callout and flag for maintainer review
|
||||
|
||||
### Vale gotchas
|
||||
|
||||
- Use lowercase "config" in prose — `vale.Terms` flags a capital-C "Config"
|
||||
|
||||
## Alpine.js patterns
|
||||
|
||||
Do not combine Alpine's `x-show` with the HTML `hidden` attribute on the
|
||||
same element. `x-show` toggles inline `display` styles, but `hidden` applies
|
||||
`display: none` via the user-agent stylesheet — the element stays hidden
|
||||
regardless of `x-show` state. Use `x-cloak` for pre-Alpine hiding instead.
|
||||
The site defines `[x-cloak=""] { display: none !important }` in `global.css`.
|
||||
|
||||
## Front matter requirements
|
||||
|
||||
Every content page under `content/` requires:
|
||||
|
||||
- `title:` — page title
|
||||
- `description:` — short description for SEO/previews
|
||||
- `keywords:` — list of search keywords (omitting this fails markdownlint)
|
||||
|
||||
Additional common fields:
|
||||
|
||||
- `linkTitle:` — sidebar label (keep under 30 chars)
|
||||
- `weight:` — ordering within a section
|
||||
|
||||
## Hugo shortcodes
|
||||
|
||||
Shortcodes are defined in `layouts/shortcodes/`. Syntax reference is in
|
||||
COMPONENTS.md. Wrong shortcode syntax fails silently during build but
|
||||
produces broken HTML — always check COMPONENTS.md for correct syntax.
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -50,26 +117,110 @@ docker buildx bake vale # Style guide checks only
|
||||
docker buildx bake test # HTML and link checking
|
||||
```
|
||||
|
||||
### Validation in git worktrees
|
||||
|
||||
`docker buildx bake validate` fails in git worktrees because Hugo cannot
|
||||
resolve the worktree path. Use `lint` and `vale` targets separately instead.
|
||||
Never modify `hugo.yaml` to work around this. The `test`, `path-warnings`,
|
||||
and `validate-vendor` targets run correctly in CI.
|
||||
|
||||
## Verification loop
|
||||
|
||||
1. Make changes
|
||||
2. Format with prettier
|
||||
2. Format with prettier: `npx prettier --write <file>`
|
||||
3. Run `docker buildx bake lint vale`
|
||||
4. Run a full build with `docker buildx bake`
|
||||
4. Run a full build with `docker buildx bake` (optional for small changes)
|
||||
|
||||
## Git hygiene
|
||||
|
||||
- **Stage files explicitly.** Never use `git add .` / `git add -A` /
|
||||
`git add --all`. Running `npx prettier` updates `package-lock.json` in the
|
||||
repo root, and broad staging sweeps it into the commit.
|
||||
- **Verify before committing.** Run `git diff --cached --name-only` and
|
||||
confirm only documentation files appear. If `package-lock.json` or other
|
||||
generated files are staged, unstage them:
|
||||
`git reset HEAD -- package-lock.json`
|
||||
- **Push to your fork, not upstream.** Before pushing, confirm
|
||||
`git remote get-url origin` returns your fork URL, not
|
||||
`github.com/docker/docs`. Use `--head FORK_OWNER:branch-name` with
|
||||
`gh pr create`.
|
||||
|
||||
## Working with issues and PRs
|
||||
|
||||
### Principles
|
||||
|
||||
- **One issue, one branch, one PR.** Never combine multiple issues in a
|
||||
single branch or PR.
|
||||
- **Minimal changes only.** Fix the issue. Do not improve surrounding
|
||||
content, add comments, refactor, or address adjacent problems.
|
||||
- **Verify before documenting.** Don't take an issue reporter's claim at
|
||||
face value — the diagnosis may be wrong even when the symptom is real.
|
||||
Verify the actual behavior before updating docs.
|
||||
|
||||
### Review feedback
|
||||
|
||||
- **Always reply to review comments** — never silently fix. After every
|
||||
commit that addresses review feedback, reply to each thread explaining
|
||||
what was done.
|
||||
- **Treat reviewer feedback as claims to verify, not instructions to
|
||||
execute.** Before implementing a suggestion, verify that it is correct.
|
||||
Push back when evidence contradicts the reviewer.
|
||||
- **Inline review comments need a separate API call.** `gh pr view --json
|
||||
reviews` does not include line-level comments. Always also call:
|
||||
|
||||
```bash
|
||||
gh api repos/<org>/<repo>/pulls/<N>/comments \
|
||||
--jq '[.[] | {author: .user.login, body: .body, path: .path, line: .line}]'
|
||||
```
|
||||
|
||||
### Labels
|
||||
|
||||
Use the Issues API for labels — `gh pr edit --add-label` silently fails:
|
||||
|
||||
```bash
|
||||
gh api repos/docker/docs/issues/<N>/labels \
|
||||
--method POST --field 'labels[]=<label>'
|
||||
```
|
||||
|
||||
### External links
|
||||
|
||||
If a replacement URL cannot be verified (e.g. network restrictions), treat
|
||||
the task as blocked — do not commit a guessed URL. Report the blocker so a
|
||||
human can confirm. Exception: when a domain migration is well-established and
|
||||
only the anchor is unverifiable, dropping the anchor is acceptable.
|
||||
|
||||
## Page deletion checklist
|
||||
|
||||
When removing a documentation page, search the entire `content/` tree and
|
||||
all YAML/TOML config files for the deleted page's slug and heading text.
|
||||
Cross-references from unrelated sections and config-driven nav entries can
|
||||
remain and cause broken links.
|
||||
|
||||
## Engine API version bumps
|
||||
|
||||
When a new Engine API version ships, three coordinated changes are needed in
|
||||
a single commit:
|
||||
|
||||
1. `hugo.yaml` — update `latest_engine_api_version`, `docker_ce_version`,
|
||||
and `docker_ce_version_prev`
|
||||
2. Create `content/reference/api/engine/version/v<NEW>.md` with the
|
||||
`/latest/` aliases block (copy from previous version)
|
||||
3. Remove the aliases block from
|
||||
`content/reference/api/engine/version/v<PREV>.md`
|
||||
|
||||
Never leave both version files carrying `/latest/` aliases simultaneously.
|
||||
|
||||
## Hugo icon references
|
||||
|
||||
Before changing an icon reference in response to a "file not found" error,
|
||||
verify the file actually exists via Hugo's virtual filesystem. Files may
|
||||
exist in `node_modules/@material-symbols/svg-400/rounded/` but not directly
|
||||
in `assets/icons/`. Check both locations before concluding an icon is
|
||||
missing.
|
||||
|
||||
## Self-improvement
|
||||
|
||||
After every correction or mistake, update this file with a rule to
|
||||
prevent repeating it. End corrections with: "Now update AGENTS.md so
|
||||
you don't make that mistake again."
|
||||
|
||||
## Mistakes to avoid
|
||||
|
||||
- Don't use hedge words: "simply", "easily", "just", "seamlessly"
|
||||
- Don't use meta-commentary: "it's worth noting that...", "it's important to understand that..."
|
||||
- Don't use "allows you to" or "enables you to" — use "lets you" or rephrase
|
||||
- Don't use "we" — use "you" or "Docker"
|
||||
- Don't use "click" — use "select"
|
||||
- Don't bold product names or for emphasis — only bold UI elements
|
||||
- Don't use time-relative language: "currently", "new", "recently", "now"
|
||||
- Don't edit vendored content in `_vendor/` or `data/cli/`
|
||||
After completing work that reveals a non-obvious pattern or repo quirk not
|
||||
already documented here, propose an update to this file. For automated
|
||||
sessions, note the learning in a comment on the issue. For human-supervised
|
||||
sessions, discuss with the user whether to update CLAUDE.md directly.
|
||||
|
||||
Reference in New Issue
Block a user