From 25ddb5a94752171663444879a28f039232477e6c Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Thu, 27 Aug 2026 19:02:21 +0200 Subject: [PATCH 1/6] Add writing standard, surface map, and issue skill; de-mechanize PR and issue templates The pr skill produced bodies that were technically correct but hard to enter fast. The What section read as a diff transcript; the Why often opened with the history of a prior PR before stating the problem; there was no front-loaded outcome for a newcomer, no way for the reviewer to check the claim, and no consistent vocabulary for what a change touches. This commit adds: - writing-style.md: shared plain-language rules (ISO 24495-1 principles, ASD-STE100 sentence mechanics, backtick conventions, anti-mechanical rules) with before/after examples from merged PRs - surfaces.md: advisory map from diff paths to human-readable surface names (Authoring, Release notes, Configuration, etc.) used for the Affects line in PRs and the area label in issues - issue/SKILL.md: new skill for filing bug reports and feature requests - Updated pr/SKILL.md: adds lead sentence, Affects line, Verify section with fenced commands, and conditional Breaking/Out-of-scope/Risk/Stack add-ons; fixes the label table to match release-drafter.yml exactly - Updated commit/SKILL.md: removes hardcoded Co-Authored-By model version - Issue templates trimmed to the two questions that matter; config.yml added to keep blank issues enabled and add a discussion link Co-Authored-By: Claude Opus 5 --- .claude/skills/commit/SKILL.md | 19 ++-- .claude/skills/issue/SKILL.md | 119 ++++++++++++++++++++++++ .claude/skills/pr/SKILL.md | 88 ++++++++++++------ .claude/skills/surfaces.md | 76 +++++++++++++++ .claude/skills/writing-style.md | 118 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/bug-report.yaml | 68 ++++++++------ .github/ISSUE_TEMPLATE/config.yml | 5 + .github/ISSUE_TEMPLATE/enhancement.yaml | 91 +++++------------- 8 files changed, 451 insertions(+), 133 deletions(-) create mode 100644 .claude/skills/issue/SKILL.md create mode 100644 .claude/skills/surfaces.md create mode 100644 .claude/skills/writing-style.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.claude/skills/commit/SKILL.md b/.claude/skills/commit/SKILL.md index bf30480b14..1c590fd7d1 100644 --- a/.claude/skills/commit/SKILL.md +++ b/.claude/skills/commit/SKILL.md @@ -5,6 +5,8 @@ description: Stage relevant files and create a well-formed git commit for the do # Commit Skill +Read [`.claude/skills/writing-style.md`](../writing-style.md) before writing the commit message. + Creates a clean, well-formed commit following the docs-builder project conventions. ## Steps @@ -24,7 +26,6 @@ Do not run `git config` yourself. Do not use `--no-verify`. ### 2. Understand what changed -Run these in parallel: ```bash git status git diff @@ -41,19 +42,19 @@ Stage specific files by name — never `git add -A` or `git add .` blindly. Excl ### 4. Write the commit message -Rules: -- **First line**: Imperative mood, ≤72 chars, no trailing period (e.g. `Add async timeout handling to assembler`) -- **Body** (optional): One short paragraph explaining *why*, not what. Skip if the title is self-explanatory. -- **Trailer**: Always append `Co-Authored-By: Claude Sonnet 4.6 (1M context) ` +- **First line**: Imperative mood, ≤72 chars, no trailing period. Front-load the outcome — a reader scanning `git log` sees this line only. +- **Body** (optional): One short paragraph explaining *why*, not what. Skip if the title is self-explanatory. Follow the sentence mechanics in `writing-style.md`. +- **Trailer**: `Co-Authored-By: ` where `` is the model name shown in your system prompt (e.g. `Claude Opus 5` or `Claude Sonnet 5`). Never hardcode a specific version — check the system prompt each time. Always pass the message via HEREDOC to avoid shell escaping issues: + ```bash git commit -m "$(cat <<'EOF' Title here Optional body explaining why. -Co-Authored-By: Claude Sonnet 4.6 (1M context) +Co-Authored-By: Claude Opus 5 EOF )" ``` @@ -72,4 +73,8 @@ If a hook fails: ### 6. Verify success -Run `git status` after the commit to confirm a clean working tree. +```bash +git status +``` + +Confirm a clean working tree. diff --git a/.claude/skills/issue/SKILL.md b/.claude/skills/issue/SKILL.md new file mode 100644 index 0000000000..ba22db230e --- /dev/null +++ b/.claude/skills/issue/SKILL.md @@ -0,0 +1,119 @@ +--- +name: issue +description: File a well-formed bug report or feature request. Use when the user asks to open an issue, report a bug, or request a feature in the docs-builder repo. +--- + +# Issue Skill + +Read [`.claude/skills/writing-style.md`](../writing-style.md) and [`.claude/skills/surfaces.md`](../surfaces.md) before writing anything. + +Files a GitHub issue that matches the repo's templates, applies correct labels, and checks for duplicates first. + +## Steps + +### 1. Check for duplicates + +Search for near-duplicates before opening anything. Link any you find in the issue body rather than filing a second. + +```bash +gh issue list --search "" --limit 10 +``` + +### 2. Determine the issue type + +- **Bug** — something that used to work stopped, or produces wrong output. Use `bug-report` structure. +- **Feature / enhancement** — something that does not exist yet, or needs to be better. Use `enhancement` structure. + +### 3. Write the title + +- ≤70 characters, no trailing period +- States the observable problem or the wanted capability — not the internal cause or the implementation + +### 4. Write the body + +**Bug report:** + +``` + + +### What happened + + + +### How to reproduce + + + +### Version or commit + + +``` + +**Feature request:** + +``` + + +### What is getting in your way + + + +### What would you like instead + + + +### Anything else + + +``` + +Formatting rules: +- Same plain-language rules as PR bodies — active voice, short sentences, no mechanical noun clusters. +- Commands and error messages in fenced blocks. +- Backticks on all identifiers: flags, config keys, file paths, method names. +- Skip any section that has nothing to say — a blank section adds noise, not structure. + +### 5. Choose labels + +File with **two or three labels**: + +1. **Type** (required, from the template): `bug` or `enhancement` +2. **Area** (one, if it fits): derived from the surface map in `surfaces.md`. Pick from the repo's existing area labels — do not invent new ones: + `authoring` · `links` · `tables` · `attributes` · `versioning` · `build` · `automation` · `migration` · `SEO` · `user-experience` · `tech-debt` · `design` +3. **`needs triage`** (always) + +These are issue labels, not release-drafter PR labels. Do not use `feature`, `chore`, `redesign`, `changelog:skip`, etc. here. + +### 6. Create the issue + +One call — title, labels, and body together: + +```bash +gh issue create \ + --title "" \ + --label "bug,<area-label>,needs triage" \ + --body "$(cat <<'EOF' +<lead sentence> + +### What happened + +... + +### Version or commit + +... +EOF +)" +``` + +Replace `bug` with `enhancement` for feature requests. Omit the area label if none fits — do not force one. + +### 7. Return the issue URL + +Always print the URL so the user can open it directly. diff --git a/.claude/skills/pr/SKILL.md b/.claude/skills/pr/SKILL.md index 9b733ecf6c..dce88df1c4 100644 --- a/.claude/skills/pr/SKILL.md +++ b/.claude/skills/pr/SKILL.md @@ -5,13 +5,14 @@ description: Create a GitHub pull request for the current branch with a focused # PR Skill -Creates a GitHub PR with a body focused on *why* and *what*, labeled for the release changelog. +Read [`.claude/skills/writing-style.md`](../writing-style.md) and [`.claude/skills/surfaces.md`](../surfaces.md) before writing anything. + +Creates a GitHub PR body that a newcomer can orient from in under a minute: front-loaded outcome, grounded Why, behaviour-led What, verifiable by the reviewer. ## Steps ### 1. Understand the branch -Run these to see what the PR contains: ```bash git status git log main..HEAD --oneline @@ -22,7 +23,7 @@ git diff main...HEAD --stat If the working tree has changes that belong in this PR, read and follow [commit](../commit/SKILL.md) first. Do not commit inline. Do not skip hooks. -### 3. Push the branch (if needed) +### 3. Push (if needed) ```bash git push -u origin HEAD @@ -30,66 +31,95 @@ git push -u origin HEAD ### 4. Write the PR title -- ≤70 characters -- Imperative mood, no trailing period -- Describes the change at a human level (not a file list) +- ≤70 characters, imperative mood, no trailing period +- States what changed at a human level — not a file list, not a symbol name +- No `[bug]` / `[feature]` / `[chore]` prefixes — the label carries the type ### 5. Write the PR body -Use this structure: +Required structure: ``` -## Why +<One or two sentences, no heading. What this changes and the effect. + A newcomer reads only this and knows whether the PR concerns them.> -<One or two sentences: the problem, gap, or need this addresses. What would go wrong without this change?> +**Affects:** <one to three surfaces from surfaces.md, most affected first> + +## Why +<Two to four sentences. The concrete failure or gap. Active voice, present tense + for current behaviour. Do not open with the history of a prior PR.> ## What +<Three to five items. Each leads with the behaviour change; name a symbol only + when the reviewer needs it to find the code.> -<What changed, at a meaningful level — not a file list. Think: what does a reviewer need to understand to evaluate this?> +## Verify +<How the reviewer confirms this works. Commands in fenced blocks with a language + tag, never inline. One context line above a block if the command needs it. + Non-command checks (a URL, a CI job, a log line) stay as prose.> +``` -## How (optional) +Conditional add-ons — each is one or two sentences with a bold lead-in, no heading: -<Only include this section if a completely new architectural mechanism was introduced that future contributors need to understand at a big-picture level. Skip for normal feature additions, fixes, or refactors — those belong in code comments, not here.> -``` +- **Breaking** — what a consumer must change and when it bites them. Pairs with the `breaking` label. +- **Out of scope** — a gap this PR deliberately leaves, so a reviewer does not raise it as a finding. +- **Risk** — shared or production state this touches. Required when the change reaches anything in `CLAUDE.md`'s "Boundaries: never touch / human-gated" list, or leaves state that a code revert will not undo. +- **Stack** — position and links: `3 of 5, on top of #3855`. A bare `Stack: 3/5` with no links is not enough. -**Do not** include bullet lists of changed files. Do not summarize what's already obvious from the diff. +**Do not** include bullet lists of changed files. Do not summarize what the diff already states plainly. ### 6. Choose exactly ONE label -Pick the single best-fit label. Apply it with `--label <label>`. +`.github/workflows/required-labels.yml` enforces exactly one release-drafter label at `mode: exactly, count: 1` — two labels or zero fails CI. Pick the single best fit. | Label | Use when | -|-------|----------| -| `breaking` | Existing behavior or public API breaks | -| `feature` | New capability that did not exist before | -| `enhancement` | Improves or extends an existing feature | -| `bug` | Fixes a defect in existing behavior | -| `fix` | Alias for bug fix (use `bug` by preference) | -| `documentation` | Docs-only change (markdown, /docs/ pages) | +|---|---| +| `breaking` | An existing config, invocation, or documented behaviour stops working | +| `feature` | A capability that did not exist before | +| `enhancement` | An existing capability got better | +| `bug` | A defect in existing behaviour is fixed | +| `documentation` | Docs-only change (`docs/` pages, not incidental doc updates in the same PR) | | `chore` | Cleanup, refactor, internal restructure — no user-visible change | | `dependencies` | Dependency version bumps | -| `automation` | CI/CD, GitHub Actions, scripts, build tooling | -| `ci` | Alias for automation (use `automation` by preference) | -| `redesign` | Frontend visual/structural redesign work | -| `changelog:skip` | Housekeeping with no changelog entry (e.g. typo fixes, config tweaks) | +| `automation` | CI/CD, GitHub Actions, build tooling | +| `redesign` | Frontend visual or structural redesign | +| `changelog:skip` | Nothing worth a changelog line | + +Never use `fix` (use `bug`) or `ci` (use `automation`) — both are release-drafter aliases that split the same changelog category. + +**`feature` vs `enhancement`:** `feature` = didn't exist; `enhancement` = existed but got better. -When in doubt between `feature` and `enhancement`: `feature` = didn't exist, `enhancement` = existed but got better. +**`breaking` guidance:** use it when an older `docs-builder` invocation or an existing repo config stops working. The canonical trigger is `Configuration` in the `**Affects:**` line plus a rename or removal — [#3856](https://github.com/elastic/docs-builder/pull/3856) removed `output:` from `changelog.yml` profiles and shipped as `feature`; it should have been `breaking`. Internal C# type renames and private method signature changes are not breaking. ### 7. Create the PR +One call — title, label, and body together. No follow-up `gh pr edit`: + ```bash gh pr create --title "<title>" --label "<label>" --body "$(cat <<'EOF' +<lead sentence(s)> + +**Affects:** <surfaces> + ## Why ... ## What -... +- ... +- ... +- ... + +## Verify + +```bash +<command> +``` EOF )" ``` ### 8. Return the PR URL -Always print the PR URL so the user can open it directly. +Always print the URL so the user can open it directly. diff --git a/.claude/skills/surfaces.md b/.claude/skills/surfaces.md new file mode 100644 index 0000000000..5466bc8c1c --- /dev/null +++ b/.claude/skills/surfaces.md @@ -0,0 +1,76 @@ +# Surface map + +Answers "what does this change affect?" from the paths in a diff. +Used by the `pr` skill to write the `**Affects:**` line, and by the `issue` skill to pick an area label. + +--- + +## How to use this map + +**Prefer an existing entry when one fits.** Consistent terms are the whole point — a reviewer who sees `Release notes` on ten PRs knows immediately what moved. + +**Coin your own term when the map is stale or a plainer word fits better.** When you do, say so in the PR body (`Affects: Contributor workflow — not in the map; proposed as an addition`) and add it here in the same PR. A coined term that never lands back in the map is a one-off, not a convention. + +--- + +## Output rules + +- **One to three surfaces**, most affected first. +- More than three means the change is either genuinely cross-cutting or should be split. +- A change with no reader-visible surface: `**Affects:** Internals only`. Do not stretch for an entry. +- `Authoring`, `Configuration`, and `CLI` are the surfaces most often *missed*, because a change to shared code reaches them indirectly. Check them before settling. +- Do **not** list `Documentation` when the `docs/` change only documents the same PR's code change. Reserve it for PRs whose point is the documentation. +- `Configuration` plus a rename or removal is the trigger to reconsider the `breaking` label. +- `Deploys & previews`, `Release notes` publishing, and the Lambdas are where the **Risk** line usually applies. Cross-reference `CLAUDE.md`'s "Boundaries: never touch / human-gated" list. +- For the test-project mapping (`Elastic.Markdown/` → `dotnet test tests/Elastic.Markdown.Tests/`, etc.), see `CLAUDE.md`. Do not duplicate it here. + +--- + +## The map + +Named for what a reader *loses* when it breaks, not for the project that implements it. + +| Surface | Primary paths | What breaks for whom | +|---|---|---| +| `Authoring` | `src/Elastic.Markdown/`, `tests/authoring/` | Markdown syntax and rendering — every doc author | +| `Navigation` | `src/Elastic.Documentation.Navigation/`, `config/navigation*.yml` | Nav trees, TOC, sidebar structure | +| `Site UI` | `src/Elastic.Documentation.Site/` | Page chrome, layout, styling, client-side behaviour | +| `API reference` | `src/Elastic.ApiExplorer/`, `src/Elastic.Documentation.OpenApiIndex/`, `src/infra/docs-lambda-openapi-index/` | OpenAPI-driven reference pages | +| `Release notes` | `src/services/Elastic.Changelog/`, `src/infra/docs-lambda-changelog-scrubber/`, `docs/cli/changelog/` | Changelog entries, bundling, publishing | +| `Search` | `src/Elastic.Documentation.Indexing/`, `src/services/search/`, `src/tooling/essc/`, `config/search.yml` | Docs search and elastic.co website search, indexing, ranking | +| `Links & redirects` | `src/Elastic.Documentation.Links/`, `src/Elastic.Documentation.LinkIndex/`, `src/infra/docs-lambda-index-publisher/`, `docs/_redirects.yml`, `config/legacy-url-mappings.yml` | Cross-repo links, link validation, redirects | +| `Assembler builds` | `src/services/Elastic.Documentation.Assembler/`, `src/tooling/docs-builder/Commands/Assembler/` | The multi-repo assembled site | +| `Isolated builds` | `src/services/Elastic.Documentation.Isolated/`, `IsolatedBuildCommand.cs` | Single-docset builds — what a repo runs on its own content | +| `Codex builds` | `src/Elastic.Codex/`, `src/tooling/docs-builder/Commands/Codex/` | Codex content assembly | +| `Docs API` | `src/api/Elastic.Documentation.Api/` | The runtime service: Ask AI, search endpoints | +| `MCP` | `src/api/Elastic.Documentation.Mcp.Remote/` | The remote MCP server and its consumers | +| `Deploys & previews` | `src/services/Elastic.Documentation.Deploying/`, `DeployCommands.cs`, `assembler-preview*.yml`, `docs-preview*-local.yml` | PR previews, S3 and CloudFront state, the redirect store | +| `Configuration` | `src/Elastic.Documentation.Configuration/`, `config/*.yml` | Config schema — a rename here breaks older `docs-builder` versions | +| `CLI` | `src/tooling/docs-builder/Commands/`, `docs/cli-schema.json` | Commands and flags — anyone scripting `docs-builder` | +| `Automation` | `.github/workflows/`, `build.sh`, `Directory.Packages.props` | CI, release plumbing, the build itself | +| `Documentation` | `docs/` | This repo's own documentation | +| `Migration` | `src/authoring/Elastic.LegacyDocs.Migration/`, `src/Elastic.Documentation.LegacyDocs/`, `src/tooling/docs-migrate/`, `src/tooling/adoc-compare/` | Legacy AsciiDoc migration tooling | +| `Contributor workflow` | `.claude/skills/`, `.github/ISSUE_TEMPLATE/`, `.github/*.md` | How contributors file issues and write PRs in this repo | + +--- + +## Issue area labels + +When the `issue` skill files a bug or feature request, it picks a type label (`bug` or `enhancement`, from the template) plus at most one area label from this set. Use the surface map to derive the area. + +These are the repo's existing issue area labels — do not invent new ones: + +`authoring` · `links` · `tables` · `attributes` · `versioning` · `build` · `automation` · `migration` · `SEO` · `user-experience` · `tech-debt` · `design` + +Plus `needs triage` on every new issue. + +Surface → area label guidance: +- `Authoring` → `authoring` +- `Navigation` → (no direct match — omit or use `user-experience`) +- `Site UI` → `design` or `user-experience` +- `Links & redirects` → `links` +- `Configuration`, `CLI` → `build` +- `Automation` → `automation` +- `Migration` → `migration` +- `Search` → (no direct match — omit) +- Other surfaces → omit the area label; `needs triage` is enough diff --git a/.claude/skills/writing-style.md b/.claude/skills/writing-style.md new file mode 100644 index 0000000000..fee2c9a440 --- /dev/null +++ b/.claude/skills/writing-style.md @@ -0,0 +1,118 @@ +# Writing style for commits, PRs, and issues + +Every commit message, PR body, and issue filed in this repo follows these rules. +Skills that write those artifacts read this file first. + +--- + +## Governing principles (ISO 24495-1) + +- **Relevant** — write for a reviewer who has not seen the branch. Cut whatever the diff already states plainly. +- **Findable** — the first sentence states the outcome. A newcomer reads it and knows whether the change concerns them. +- **Understandable** — plain words, short sentences, no assumed context. +- **Usable** — after reading, the reviewer can evaluate, revert, or reproduce. + +--- + +## Sentence mechanics (ASD-STE100, adapted) + +*The ASD-STE100 sentence rules apply here. Its ~900-word approved vocabulary does not — it rejects `assembler`, `idempotent`, and `reconciliation` and its clipped imperative register produces mechanical prose. Take the mechanics, drop the dictionary.* + +- Active voice. Name the actor. "A retry clears the lock", not "The lock is cleared on retry". +- One idea per sentence. Around 25 words maximum. +- Six sentences maximum per paragraph. +- Present tense for how the code behaves now; past tense only for what it used to do. +- No noun cluster longer than three words. "shallow clone lock collision guard" → "a guard against lock collisions in shallow clones". +- One term per concept, every time. Do not alternate *job* / *step* / *task* for the same thing. +- Keep articles: "The assembler runs", not "Assembler runs". +- One subordinate clause per sentence. No em-dash pile-ups. + +--- + +## Fenced blocks for anything runnable + +A command, a config snippet, a YAML fragment, an error message, or a stack trace goes in a fenced code block with a language tag — not inline, however short. + +Inline backticks *name* a thing. A fenced block holds something the reader runs, pastes, or reads as output. + +- `--no-delete` inline (naming the flag) +- Command in a block: + ```bash + docs-builder assembler deploy update-redirects --no-delete preview + ``` + +Test names go in `#` comments inside the block next to the command that runs them, not in prose beside it: + +```bash +dotnet test tests/Elastic.Changelog.Tests/ +# BundleChangelogs_WithPrsFilter_MatchesFilenameDigitsWhenYamlPrsEmpty — scrubbed-entry case +``` + +--- + +## Backticks, used liberally + +Every identifier gets backticks, every time, including repeat mentions. This covers: + +- Types, methods, properties, fields: `IGitRepository.Fetch`, `GitLocks.ClearStale` +- CLI commands and flags: `docs-builder`, `--no-delete`, `--prs` +- Env vars: `ASSEMBLER_PREVIEW_PATH_PREFIX` +- File and directory paths: `ci.yml`, `src/services/Elastic.Changelog/` +- YAML keys (with trailing colon): `output:`, `prs:` +- Config values, labels, package names, branch names, exit codes + +Prose that names a symbol bare is wrong even when it reads fine: + +| Wrong | Right | +|---|---| +| IGitRepository.Fetch returned void | `IGitRepository.Fetch` returned `void` | +| pass --no-delete | pass `--no-delete` | +| the synthetics job in ci.yml | the `synthetics` job in `ci.yml` | + +Do **not** backtick prose nouns that merely share a name with code — the assembler, the scrubber, a profile — unless you mean the literal identifier. + +--- + +## Anti-mechanical rules for "What" sections + +Lead with the behaviour change; name the symbol second when the reviewer needs it to find the code. + +| Wrong | Right | +|---|---| +| `` `GitLocks.ClearStale` sweeps `*.lock` files before each retry `` | A retry clears stale `*.lock` files under `.git/` before it runs | +| `` **`IsolatedBuildService.Build`**: captures the `GenerateAll` result `` | The build result is captured and `redirects.json` is written to the output directory | + +**Banned openers** for bullet points: +- "Added", "Updated", "Changed", "Refactored", "Modified" +- Any bullet that starts with a file path or a symbol name +- Any bullet that only restates a filename + +**Three to five items in a "What".** More than five is a signal the change should be split. + +--- + +## Before/after examples from merged PRs + +These are the rules in action. If a new rule does not survive this test, the rule is wrong. + +**#3951 — `## What`, first bullet:** + +> ❌ `GitLocks.ClearStale(IFileSystem, ...)` sweeps `*.lock` files under `.git/` before each retry. Called only from the retry path — never before attempt 1, where a lock could belong to a concurrent process. + +> ✅ A retry clears stale `*.lock` files under `.git/` before it runs. The first attempt is never affected — a lock there can belong to a live process. + +**#3941 — opening of `## Why`:** + +> ❌ [#3911](https://github.com/elastic/docs-builder/pull/3911) tried to fix stale CDN pool listings by bringing back `changelog/{org}/{repo}/{branch}/registry.json`. That approach was rejected… + +> ✅ Scrubbing strips `prs:` from the public copies of private-repo entries. `--prs` joined only on that YAML field, so those entries dropped out of the bundle with no error. + +The history of a rejected PR is not the problem this PR solves. Lead with the problem. + +**#3856 — label:** + +> ❌ `feature` + +> ✅ `breaking` + +`output:` was removed from `changelog.yml` profiles — an existing config stops working. The `Configuration` surface plus a removal is the trigger: reconsider `breaking`. See [`surfaces.md`](surfaces.md). diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index dc43518e47..332ca93bd7 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -1,38 +1,50 @@ -name: "Bug Report" -description: "File a bug report." -labels: ["bug"] +name: Bug Report +description: Something is broken or producing wrong output. +labels: ["bug", "needs triage"] projects: ["elastic/1625"] body: - - type: "textarea" - id: description + - type: textarea + id: what-happened attributes: - label: "Describe the bug" - description: "A clear and concise description of what the bug is. If applicable, add screenshots to help explain your problem." + label: What happened? + description: > + What did you see? Include the command you ran and the exact output or error. + Expected behaviour is welcome too — one field is easier than two. + placeholder: | + I ran `docs-builder build` against a docset with a cross-repo link. The build + succeeded but the link resolved to a 404. I expected it to fail the build or + produce a working URL. + + Error output: + ``` + <paste here> + ``` validations: required: true - - type: "textarea" - id: expected - attributes: - label: "Expected behavior" - description: "A clear and concise description of what you expected to happen." - validations: - required: true - - type: "textarea" + + - type: textarea id: repro attributes: - label: "Steps to reproduce" - description: "If relevant, provide steps to reproduce the issue." + label: How can we reproduce it? + description: > + Minimal steps or a command plus the file it ran against. + Skip this if "What happened?" already covers it. + placeholder: | + ```bash + docs-builder build --path-prefix /docs + ``` + Using `_docset.yml` with `cross_links: [elasticsearch]` and an `xref:` to a + missing anchor. validations: required: false - - type: "checkboxes" - id: tooling + + - type: input + id: version attributes: - label: "Tooling" - description: "Select the tool this bug relates to." - options: - - label: "docs-builder" - required: false - - label: "migration tooling" - required: false - - label: "I'm not sure" - required: false + label: Version or commit + description: > + Output of `docs-builder --version`, or the commit SHA if building from source. + This is the most useful piece of triage data. + placeholder: "0.11.0 / abc1234" + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..47ccb50c12 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: docs-eng-team discussions + url: https://github.com/elastic/docs-eng-team/discussions + about: Questions about documentation tooling, process, or authoring that are not defects or feature requests. diff --git a/.github/ISSUE_TEMPLATE/enhancement.yaml b/.github/ISSUE_TEMPLATE/enhancement.yaml index d6881173ac..8dc4868a02 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yaml +++ b/.github/ISSUE_TEMPLATE/enhancement.yaml @@ -1,90 +1,43 @@ name: Feature Request -description: Suggest an idea for improving docs-builder. -title: "[Feature Request]: " -labels: ["enhancement"] +description: Something is missing or could work better. +labels: ["enhancement", "needs triage"] body: - - type: markdown - attributes: - value: | - Thanks for taking the time to suggest an improvement to docs-builder! Please fill out this form as completely as possible. - - - type: checkboxes - attributes: - label: Prerequisites - description: Please verify you have completed the following - options: - - label: I have searched existing issues to ensure this feature hasn't already been requested - required: true - - label: I have tested using the latest version of docs-builder - required: true - - type: textarea id: problem attributes: - label: What problem are you trying to solve? - description: | - Describe the context and limitation you're encountering. Remember that it might not be obvious to others why this is important! + label: What is getting in your way? + description: > + The concrete limitation. What are you trying to do, and what stops you? placeholder: | - Example: When building documentation for my project, I often need to update the revision date at the top of each file. Currently, I have to manually edit each file, which is time-consuming and error-prone. + I maintain a docset that builds with `docs-builder build` and a second one that + builds with the assembler. When I run link validation locally, it only checks + links within the current docset — I cannot catch broken cross-repo references + before pushing. validations: required: true - type: textarea id: solution attributes: - label: Proposed Solution - description: | - Describe your proposed solution. Include as much detail as you can, but remember that there might be other solutions we haven't thought of! + label: What would you like instead? + description: > + Your proposed change or outcome. A clear outcome is enough — a specific + implementation is welcome but not required. placeholder: | - Example: Add a CLI flag --auto-update-revision-date that automatically updates a specified metadata field in all documentation files when building. + A `--check-cross-links` flag for `docs-builder build` that resolves xref: links + against a local clone of the referenced repo (or a cached link index) and fails + the build when any resolve to a missing anchor. validations: required: true - type: textarea - id: examples - attributes: - label: Examples and Research - description: | - Please provide any relevant examples, research, or references that support this feature request: - - Similar features in other documentation tools - - Code samples showing how you'd use this feature - - Links to relevant standards or conventions - - Screenshots or diagrams of your proposed solution - placeholder: | - - MkDocs has a similar feature using their `git-revision-date-localized` plugin - - Jekyll's `last_modified_at` plugin demonstrates this functionality - validations: - required: false - - - type: textarea - id: alternatives + id: context attributes: - label: Alternative Solutions - description: | - What alternative solutions have you considered or tried? Why aren't they sufficient? + label: Anything else? + description: > + Examples from other tools, links, screenshots, or context that did not fit above. placeholder: | - I've tried using git hooks to update the dates, but this doesn't work well in CI/CD pipelines. + MkDocs's `--strict` flag gives a similar signal for internal links. The Elastic + link index at https://... might already have the data needed to do this. validations: required: false - - - type: textarea - id: additional-context - attributes: - label: Additional Context - description: Add any other context about the feature request here. - placeholder: | - - This would be particularly useful for compliance documentation where revision dates are mandatory - - Could potentially integrate with git history for more accurate dating - validations: - required: false - - - type: dropdown - id: priority - attributes: - label: How important is this feature to you? - options: - - Nice to have - - Important - - Critical - validations: - required: true From bcefe2cf7460d9b86716ec913dd4436796d677a7 Mon Sep 17 00:00:00 2001 From: Martijn Laarman <Mpdreamz@gmail.com> Date: Thu, 27 Aug 2026 19:10:05 +0200 Subject: [PATCH 2/6] Replace hardcoded Co-Authored-By model name with prose guidance The example HEREDOC hardcoded "Claude Opus 5", which would go stale on every model update. The trailer rule now instructs the agent to use whatever attribution feels accurate for the model it's running as. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- .claude/skills/commit/SKILL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/skills/commit/SKILL.md b/.claude/skills/commit/SKILL.md index 1c590fd7d1..c4d30b9de0 100644 --- a/.claude/skills/commit/SKILL.md +++ b/.claude/skills/commit/SKILL.md @@ -44,7 +44,7 @@ Stage specific files by name — never `git add -A` or `git add .` blindly. Excl - **First line**: Imperative mood, ≤72 chars, no trailing period. Front-load the outcome — a reader scanning `git log` sees this line only. - **Body** (optional): One short paragraph explaining *why*, not what. Skip if the title is self-explanatory. Follow the sentence mechanics in `writing-style.md`. -- **Trailer**: `Co-Authored-By: <model> <noreply@anthropic.com>` where `<model>` is the model name shown in your system prompt (e.g. `Claude Opus 5` or `Claude Sonnet 5`). Never hardcode a specific version — check the system prompt each time. +- **Trailer**: Add a `Co-Authored-By:` line that identifies the model that helped write this commit. Use whatever attribution feels accurate — the model name you know yourself to be running as, or simply `Claude` if you are uncertain. The address is always `noreply@anthropic.com`. The point is honest attribution, not a precise version string. Always pass the message via HEREDOC to avoid shell escaping issues: @@ -54,7 +54,7 @@ Title here Optional body explaining why. -Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> +Co-Authored-By: Claude <noreply@anthropic.com> EOF )" ``` From ce98fb256b65bcfa9d80cd4922b9f48ea82e3bef Mon Sep 17 00:00:00 2001 From: Martijn Laarman <Mpdreamz@gmail.com> Date: Thu, 27 Aug 2026 19:10:38 +0200 Subject: [PATCH 3/6] Add Agentic Skills surface to map Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- .claude/skills/surfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/skills/surfaces.md b/.claude/skills/surfaces.md index 5466bc8c1c..10e80c8210 100644 --- a/.claude/skills/surfaces.md +++ b/.claude/skills/surfaces.md @@ -50,7 +50,7 @@ Named for what a reader *loses* when it breaks, not for the project that impleme | `Automation` | `.github/workflows/`, `build.sh`, `Directory.Packages.props` | CI, release plumbing, the build itself | | `Documentation` | `docs/` | This repo's own documentation | | `Migration` | `src/authoring/Elastic.LegacyDocs.Migration/`, `src/Elastic.Documentation.LegacyDocs/`, `src/tooling/docs-migrate/`, `src/tooling/adoc-compare/` | Legacy AsciiDoc migration tooling | -| `Contributor workflow` | `.claude/skills/`, `.github/ISSUE_TEMPLATE/`, `.github/*.md` | How contributors file issues and write PRs in this repo | +| `Agentic Skills` | `.claude/skills/`, `.github/ISSUE_TEMPLATE/`, `.github/*.md` | The AI-assisted workflows for commits, PRs, issues, and reviews | --- From 7bf7e6706a562a86b541789b55aedfcbb21a44fb Mon Sep 17 00:00:00 2001 From: Martijn Laarman <Mpdreamz@gmail.com> Date: Thu, 27 Aug 2026 19:23:26 +0200 Subject: [PATCH 4/6] Use h4 subheadings in What sections instead of bullets Bullets forced each item into one sentence of textual soup. Subheadings give each change breathing room for prose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- .claude/skills/pr/SKILL.md | 7 +++++-- .claude/skills/writing-style.md | 10 ++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.claude/skills/pr/SKILL.md b/.claude/skills/pr/SKILL.md index dce88df1c4..7b7c0a491b 100644 --- a/.claude/skills/pr/SKILL.md +++ b/.claude/skills/pr/SKILL.md @@ -50,8 +50,11 @@ Required structure: for current behaviour. Do not open with the history of a prior PR.> ## What -<Three to five items. Each leads with the behaviour change; name a symbol only - when the reviewer needs it to find the code.> + +#### <name or short label> +<Prose paragraph. Lead with behaviour, not a symbol or path. Name a symbol only + when the reviewer needs it to find the code. Two to four sentences max. + Three to five sections total.> ## Verify <How the reviewer confirms this works. Commands in fenced blocks with a language diff --git a/.claude/skills/writing-style.md b/.claude/skills/writing-style.md index fee2c9a440..928e2f397e 100644 --- a/.claude/skills/writing-style.md +++ b/.claude/skills/writing-style.md @@ -75,6 +75,8 @@ Do **not** backtick prose nouns that merely share a name with code — the assem ## Anti-mechanical rules for "What" sections +`## What` uses `####` subheadings, not bullet points. Each subheading names the thing that changed (a file, a command, a concept). The prose under it states what changed and why it matters — two to four sentences, same plain-language rules as everywhere else. + Lead with the behaviour change; name the symbol second when the reviewer needs it to find the code. | Wrong | Right | @@ -82,12 +84,12 @@ Lead with the behaviour change; name the symbol second when the reviewer needs i | `` `GitLocks.ClearStale` sweeps `*.lock` files before each retry `` | A retry clears stale `*.lock` files under `.git/` before it runs | | `` **`IsolatedBuildService.Build`**: captures the `GenerateAll` result `` | The build result is captured and `redirects.json` is written to the output directory | -**Banned openers** for bullet points: +**Banned openers** for the prose paragraph: - "Added", "Updated", "Changed", "Refactored", "Modified" -- Any bullet that starts with a file path or a symbol name -- Any bullet that only restates a filename +- Any sentence that starts with a file path or a symbol name +- Any paragraph that only restates the subheading -**Three to five items in a "What".** More than five is a signal the change should be split. +**Three to five `####` sections in a "What".** More than five is a signal the change should be split. --- From 8bf8cb64135701f3025bc612dd763dadfc4b75ce Mon Sep 17 00:00:00 2001 From: Martijn Laarman <Mpdreamz@gmail.com> Date: Thu, 27 Aug 2026 19:25:49 +0200 Subject: [PATCH 5/6] Verify section: real local steps only, not agent self-checks Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- .claude/skills/pr/SKILL.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.claude/skills/pr/SKILL.md b/.claude/skills/pr/SKILL.md index 7b7c0a491b..bdd4c5ddf3 100644 --- a/.claude/skills/pr/SKILL.md +++ b/.claude/skills/pr/SKILL.md @@ -57,9 +57,11 @@ Required structure: Three to five sections total.> ## Verify -<How the reviewer confirms this works. Commands in fenced blocks with a language - tag, never inline. One context line above a block if the command needs it. - Non-command checks (a URL, a CI job, a log line) stay as prose.> +<How a reviewer confirms this locally. Use real commands they would run: + `./build.sh`, `dotnet test`, `npm run test`, `dotnet run --project …`. + If there is no clear local verification step, omit this section entirely. + Do not list CI checks, YAML linting, or bash scripts an agent would run + to prove their own work — those are not reviewer steps.> ``` Conditional add-ons — each is one or two sentences with a bold lead-in, no heading: From b909ef84fda05c9552b99c84ce92f768a158558b Mon Sep 17 00:00:00 2001 From: Martijn Laarman <Mpdreamz@gmail.com> Date: Thu, 27 Aug 2026 19:27:10 +0200 Subject: [PATCH 6/6] What sections: conceptual blocks, not file names Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --- .claude/skills/pr/SKILL.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.claude/skills/pr/SKILL.md b/.claude/skills/pr/SKILL.md index bdd4c5ddf3..cd6f093185 100644 --- a/.claude/skills/pr/SKILL.md +++ b/.claude/skills/pr/SKILL.md @@ -51,10 +51,10 @@ Required structure: ## What -#### <name or short label> -<Prose paragraph. Lead with behaviour, not a symbol or path. Name a symbol only - when the reviewer needs it to find the code. Two to four sentences max. - Three to five sections total.> +#### <Conceptual label — not a filename> +<Prose paragraph. Group by what changed conceptually, not by which files moved. + Lead with behaviour. Name a symbol only when the reviewer needs it to find the code. + Two to four sentences. Three to five sections total.> ## Verify <How a reviewer confirms this locally. Use real commands they would run: