From e4c479da586b67cfbff1fc06ef1e3ff6a07ebf15 Mon Sep 17 00:00:00 2001 From: Max Haarhaus Date: Mon, 10 Aug 2026 00:29:33 -0400 Subject: [PATCH] feat(skills): create writing-technical-docs first draft --- README.md | 1 + .../references/code-review.md | 9 +- skills/writing-skills/SKILL.md | 6 + skills/writing-technical-docs/SKILL.md | 142 ++++++++++++++ skills/writing-technical-docs/evals/NOTES.md | 28 +++ .../writing-technical-docs/evals/evals.json | 62 +++++++ .../fixtures/docblock-comment-scale/config.ts | 21 +++ .../references/doc-types.md | 103 +++++++++++ .../references/formatting.md | 175 ++++++++++++++++++ .../references/style-principles.md | 128 +++++++++++++ 10 files changed, 674 insertions(+), 1 deletion(-) create mode 100644 skills/writing-technical-docs/SKILL.md create mode 100644 skills/writing-technical-docs/evals/NOTES.md create mode 100644 skills/writing-technical-docs/evals/evals.json create mode 100644 skills/writing-technical-docs/evals/fixtures/docblock-comment-scale/config.ts create mode 100644 skills/writing-technical-docs/references/doc-types.md create mode 100644 skills/writing-technical-docs/references/formatting.md create mode 100644 skills/writing-technical-docs/references/style-principles.md diff --git a/README.md b/README.md index 763bc39..b70ae41 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ Slow-powers provides a set of highly focused skills that ensure your agent opera 5. **`verifying-development-work`** — Requires running actual test/build commands and presenting concrete evidence before any success claim, with a final review pass over the change, code AND comments, before work is handed back. 6. **`writing-skills`** — Helps write and edit skills, following the same best practices that guide slow-powers itself. 7. **`evaluating-skills`** — Teaches the agent how to run skill evals, so the value of skills and prose changes can be objectively assessed. +8. **`writing-technical-docs`** — Guides the agent's technical writing — code comments, PR descriptions, READMEs, design docs — with a scale-sized writing process and evergreen-content rules that keep docs free of session narration. ## Why trust these skills? diff --git a/skills/verifying-development-work/references/code-review.md b/skills/verifying-development-work/references/code-review.md index cbfe3fb..a8f087f 100644 --- a/skills/verifying-development-work/references/code-review.md +++ b/skills/verifying-development-work/references/code-review.md @@ -77,7 +77,10 @@ Close with a one-line verdict. ## Clean the comments while reviewing -Comments are part of the diff. Keep only comments that earn their place: +Comments are part of the diff — and they're documentation, so the +`slow-powers:writing-technical-docs` skill's evergreen rules apply here at full strength: +comments are re-read for months and must describe the code, not the session that +wrote them. Keep only comments that earn their place: - **Keep exported documentation** such as concise jsdoc or equivalent docs that appear in generated docs or editor hints. @@ -90,6 +93,10 @@ Comments are part of the diff. Keep only comments that earn their place: - **Extract the kernel** from mixed comments: keep the one non-obvious reason, rewritten tightly if needed, and delete the surrounding narration. +When a comment you're keeping or writing needs structure or phrasing guidance — +doc-block conventions, evergreen wording — `slow:powers:writing-technical-docs` owns it; +its references cover doc types and formatting. + Comment-only edits do not change behavior. They do not require re-verification by themselves, but they should happen here so the returned diff is ready for a human to read. diff --git a/skills/writing-skills/SKILL.md b/skills/writing-skills/SKILL.md index b0ef606..29692ea 100644 --- a/skills/writing-skills/SKILL.md +++ b/skills/writing-skills/SKILL.md @@ -296,6 +296,12 @@ it. See `slow-powers:evaluating-skills` ("Seeding conversation context") and its ## Further reading - `slow-powers:evaluating-skills` — phase 2: measuring whether the draft works +- `slow-powers:writing-technical-docs` — the general technical-writing skill + (comments, PR descriptions, READMEs, design docs). This skill is the doc-type + authority for skills: it owns skill structure, frontmatter, and skill-specific + prose conventions. Where this skill is silent about the prose itself — clarity, + concision, sentence construction — writing-technical-docs' style principles apply. + On any conflict, this skill wins. - [Persuasion principles](references/persuasion-principles.md) — research foundation for discipline language - [agentskills.io best-practices](https://agentskills.io/skill-creation/best-practices) and [optimizing-descriptions](https://agentskills.io/skill-creation/optimizing-descriptions) — diff --git a/skills/writing-technical-docs/SKILL.md b/skills/writing-technical-docs/SKILL.md new file mode 100644 index 0000000..2c31856 --- /dev/null +++ b/skills/writing-technical-docs/SKILL.md @@ -0,0 +1,142 @@ +--- +name: writing-technical-docs +description: Use when writing or editing technical documentation of any size — code comments, doc blocks, commit messages, PR descriptions, review comments, READMEs, design docs, wikis, or user guides — whether drafting new content or revising existing text. +--- + +# Writing Technical Docs + +## Overview + +Technical writing runs through almost every development task: the README, the PR +description, the doc comment, the design doc. This skill provides a repeatable writing +process — audience, gather, structure, draft, review — whose depth **scales with the +doc**, plus reference docs to consult for specific questions. + +> **The scale rule:** size every step of the process to the doc. A doc-block comment +> has a conventional structure and needs no outline; a one-line review comment needs +> no review checklist; an engineering blog post or design doc earns the full loop. +> When in doubt, do less — but the review step scales down, never to zero. + +**Not for:** authoring skills (`slow-powers:writing-skills` owns the skill doc type +and takes precedence; see Related skills), or non-documentation replies (chat +answers, status updates). + +## Step 0: decide the audience and style + +Before writing, decide who reads this and what register fits. This decision is the +metric every later choice is checked against — structure, depth, terminology, tone. +One line of thought for a comment; an explicit audience sentence near the top of a +long doc. [doc-types.md](references/doc-types.md) lists per-type audience and +structure defaults; use them when the doc matches a type. + +## The process + +```mermaid +flowchart TD + start([Doc to write]) --> audience[Decide audience
and style] + audience --> gather[Gather only what
the doc needs] + gather --> structure{Conventional structure
for this doc type?} + structure -->|yes| use[Use it — done deciding] + structure -->|no| outline[Outline; split large docs into
self-contained sections] + use --> draft[Draft for the audience,
evergreen] + outline --> draft + draft --> review{Doc size?} + review -->|small| spot[Reread once: evergreen,
right for the reader] + review -->|large| full[Review checklist +
reference docs] + spot --> done([Hand off]) + full --> findings{Actionable findings?} + findings -->|yes| draft + findings -->|no| done +``` + +### Gather information + +The goal is a good doc, not a thorough investigation. Collect only what the doc needs: +- Reuse what the session already established; don't re-verify confirmed facts or + re-read code you just wrote. +- Verify the specific claims the doc will make — no more. If gathering starts to feel + like its own research project, stop and write what you know; note genuine open + questions in the draft instead. + +### Structure the doc + +- First check [doc-types.md](references/doc-types.md): if the doc matches a type, its + conventional structure applies and this step is done. A doc-block comment has an + exact structure; there is nothing extra to consider. +- For a large doc, write the outline and treat each section as its own small doc — + the process applies recursively: each section makes sense alone, and together they + make sense combined. + +### Draft + +This is the step where the skill has the least to say — you already write well. Two +orientations, held as *spirit*, not boxes to tick: + +- **Write for the step-0 audience.** Depth, terms, and tone follow from who reads it. + When a choice is hard, re-ask the audience question. +- **Write evergreen.** Describe the system or topic as it is, not the session that + produced the text: no "now supports", "currently", "the new parser", "I moved this + into `utils.ts`". Assume the output lives for months; justify exceptions (release + notes, changelogs) rather than assuming them. The word list and exceptions live in + [style-principles.md](references/style-principles.md#timeless-evergreen-documentation) + — skim it once, don't memorize it. + +### Review the draft + +Review always happens; only its depth scales. A comment or one-paragraph doc gets a +single reread through two lenses — *is it evergreen?* and *is it right for this +reader?* A substantial doc (a page or more) earns the checklist: + +``` +- [ ] Audience and style: every section serves the reader decided in step 0; depth + and terminology match what they know +- [ ] Evergreen: no time-anchored words ("now", "currently", "new", "soon"), no + session narration, no promises of future features +- [ ] Claims: every performance, cost, or security claim is verifiable and sourced; + no superlatives or guarantees +- [ ] Structure: follows the doc-type convention; headings nest without gaps; each + section stands alone +- [ ] Formatting: code, commands, placeholders, lists, tables, and notices verified + against references/formatting.md +- [ ] Links: each one necessary, descriptive, and resolving +``` + +Copy the checklist into your persistent task tracker when it applies. Judge each item +— a real "not applicable" is a pass, a shrug is not. Keep findings **actionable and +verifiable**: fix it or consciously drop it, but no open-ended style debates and no +back-and-forth over taste. + +The reference docs are **review-time and lookup tools, not pre-draft reading**. Open +[formatting.md](references/formatting.md) when a content type appears in the doc; +open [style-principles.md](references/style-principles.md) to ground a style +decision or a review finding. Consult the online source guides only for details that +may have changed since these references were distilled. + +## Failure modes — both directions + +| Failure | Reality | +|---------|---------| +| "It's just a small doc — skip the process" | The process scales down to seconds, never to zero. The two-lens reread is the floor. | +| Researching "a bit more" before writing | Gathering serves the doc. When it becomes its own investigation, write what you have. | +| Reading style guides before drafting | References are for drafting lookups and review verification. Pre-draft reading is the time sink this skill exists to prevent. | +| Full checklist on a one-line comment | Over-ceremony is as much a failure as no review. Scale is the rule. | +| Checklisting — justifying each item away | A rule satisfied in letter but not spirit was not applied. Weigh justifications or make the edit. | +| Narrating the session in the doc | "I changed X", "this now works", "as of this PR" describe the edit, not the system. Describe the system. | + +## Reference docs + +| File | Read it when… | +|------|---------------| +| [references/style-principles.md](references/style-principles.md) | A style or tone question comes up while drafting; a review finding needs grounding; you need the evergreen word list. | +| [references/formatting.md](references/formatting.md) | A doc contains headings, lists, tables, procedures, notices, code, commands, placeholders, UI references, API comments, filenames, links, dates, or numbers — verify the formatting against it. | +| [references/doc-types.md](references/doc-types.md) | Deciding a doc's structure or audience defaults: comments, commit messages, PRs, reviews, READMEs, design docs, release notes. | + +## Related skills + +- `slow-powers:writing-skills` — the doc-type authority for skills: it owns skill + structure, frontmatter, and skill-specific prose conventions (descriptions, + rationalization-proofing, discipline framing). When writing a skill, this skill's + style principles still govern the prose where writing-skills is silent — on any + conflict, writing-skills takes precedence. +- `slow-powers:verifying-development-work` — owns the review pass before handing back + code changes; its comment-hygiene checks defer to this skill's evergreen rules. diff --git a/skills/writing-technical-docs/evals/NOTES.md b/skills/writing-technical-docs/evals/NOTES.md new file mode 100644 index 0000000..72b725a --- /dev/null +++ b/skills/writing-technical-docs/evals/NOTES.md @@ -0,0 +1,28 @@ +# Eval notes — writing-technical-docs + +**Status: proposed, not yet run.** Authored with the skill in the same change (issue +\#273). The suite is deliberately unexecuted: eval-magic whole-skill runs are not yet +reliable enough to validate complete skills, and the repo is shipping <1.0 skills +"vibes-verified" with evals slated to run as a 1.0 task. Do not treat this file as +evidence of improvement until a Mode A run (with_skill vs without_skill) has been +executed and recorded here. + +## Coverage intent + +One case per headline behavior, per the evaluating-skills decomposition guidance: + +- `readme-for-cli-cold` — cold trigger; audience-first process and conventional + README structure; evergreen content in a fresh doc. +- `seeded-pr-description-narration` — **seeded** mid-session case (competing + attractor: momentum + user wants speed); the evergreen rule must strip session + narration the seed made salient. Cold contrast is the README case. +- `docblock-comment-scale` — the scale rule in both directions: no large-doc ceremony + for a single comment, and no external style-guide research (the time-waste probe). + Uses `fixtures/docblock-comment-scale/config.ts`. + +## When this gets run + +- Mode A (new skill). Suggested follow-ups once reliable: an over-ceremony case at + README scale (full checklist expected there, unlike the comment case), and a + checklisting probe (a draft that "satisfies" the evergreen rule with a hollow + justification and must still be fixed). diff --git a/skills/writing-technical-docs/evals/evals.json b/skills/writing-technical-docs/evals/evals.json new file mode 100644 index 0000000..e6cf3b1 --- /dev/null +++ b/skills/writing-technical-docs/evals/evals.json @@ -0,0 +1,62 @@ +{ + "skill_name": "writing-technical-docs", + "evals": [ + { + "id": "readme-for-cli-cold", + "prompt": "I just finished a small CLI tool in this repo — csv2json.ts, converts CSV to JSON, supports --delimiter and --pretty flags. Write the README for it.", + "expected_output": "Cold trigger for the full process at small-medium scale. The agent should load writing-technical-docs (eval-magic's automatic skill-invocation meta-check confirms firing, so no assertion re-checks it), decide the audience (a first-time evaluator, then a new user) and take the conventional README structure from references/doc-types.md (what it is, quickstart/install, usage, where to go deeper) instead of inventing one, and hand back a README whose lasting content is evergreen — no time-anchored words and no narration of the session that produced the tool.", + "assertions": [ + { + "id": "evergreen_content", + "type": "llm_judge", + "rubric": "Does the README avoid time-anchored wording ('new', 'now', 'currently', 'just', 'recently', 'latest') and avoid narrating the work session ('I wrote', 'this tool was just finished', 'as of this commit')? PASS if the content describes the tool as it is and would read correctly a year from now. FAIL if any time-anchored or session-narrating phrasing appears." + }, + { + "id": "readme_structure_for_evaluator", + "type": "llm_judge", + "rubric": "Does the README follow the conventional structure (what it is, then install/quickstart, then usage covering --delimiter and --pretty) and read as written for someone evaluating or using the tool for the first time, rather than for its author? PASS if both hold. FAIL if the structure is invented idiosyncratically or the framing assumes the reader built the tool." + } + ] + }, + { + "id": "seeded-pr-description-narration", + "prompt": "[The following is the conversation so far in this session. You are the assistant; continue from the final user turn.]\n\nUser: The retry logic in src/client.ts is dropping errors — when all retries are exhausted the caller gets a generic Error instead of the last real one. Fix it and add a test.\n\nAssistant: Fixed. The retry-exhausted path in src/client.ts now rethrows the last underlying error instead of wrapping it in a generic one, and client.test.ts has a new test covering it. Took some digging — the bug was in the wrapper swallowing the cause chain. Tests pass.\n\nUser: Great. Write the PR description so I can get this up for review.", + "expected_output": "Seeded case: the session has momentum (fix done, tests green, user wants speed) and the seed carries narration material ('took some digging', 'the bug was in...'). Correct behavior is to load writing-technical-docs and write a PR description whose lasting parts — what changed and why — stand alone: the what/why of the change and its user-visible effect, how it was verified, with NO session narration in those parts. A PR is an evergreen-relaxed doc type, but its 'why' gets quoted into merge commits and must make sense later. This is the seeded counterpart to readme-for-cli-cold: the skill must fire mid-session under momentum, and the evergreen rule must strip the narration the seed made salient.", + "assertions": [ + { + "id": "no_session_narration", + "type": "llm_judge", + "rubric": "Does the PR description's what/why content avoid narrating the work session — no 'I spent a while tracking down', 'after debugging', 'this now works', 'previously the code would' as framing, no effort or chronology reporting? PASS if the description states the change, its motivation, and its effect as standing facts. FAIL if it reports the session's events or effort as the content." + }, + { + "id": "pr_covers_what_why_verification", + "type": "llm_judge", + "rubric": "Does the PR description cover what changed (retry exhaustion now rethrows the last underlying error), why (callers received a generic error), and how it was verified (new test in client.test.ts, suite green)? PASS if all three are present and accurate. FAIL if any is missing or wrong." + } + ] + }, + { + "id": "docblock-comment-scale", + "prompt": "Add a doc comment to the parseConfig function in config.ts explaining what it does.", + "files": ["fixtures/docblock-comment-scale/config.ts"], + "expected_output": "Scale case, measuring both failure directions the skill warns about. The agent should load writing-technical-docs (a doc comment is a doc), then do the SMALL version of the process: take the conventional doc-block structure (one-sentence summary, parameters, return value — per references/doc-types.md and the API-comment conventions in references/formatting.md), write it evergreen, and finish with the two-lens reread. It must NOT do the large-doc ceremony: no copying the six-item review checklist into a tracker, no outline step, and — the time-waste probe — no fetching online style guides (developers.google.com, stylepedia.net) before or after drafting. Correct behavior is seconds of thought, not a process performance.", + "assertions": [ + { + "id": "no_style_guide_research", + "type": "llm_judge", + "rubric": "Did the agent write the comment WITHOUT consulting external style references — no web fetches or searches of developers.google.com, stylepedia.net, or other writing-style guides at any point? PASS if no external style-guide research appears in the transcript. FAIL if the agent fetched or searched style documentation for this one comment." + }, + { + "id": "comment_conventional_and_evergreen", + "type": "llm_judge", + "rubric": "Does the added doc comment follow doc-block conventions (opens with a one-sentence summary of what parseConfig does; documents parameters and return value) and stay evergreen (no 'now', 'currently', 'new', no session narration)? PASS if both hold. FAIL if the comment is missing either convention or contains time-anchored wording." + }, + { + "id": "no_large_doc_ceremony", + "type": "llm_judge", + "rubric": "Did the agent scale the process down for a single comment — no multi-item review checklist tracked or recited, no outline or structure deliberation, no multi-source style research? PASS if the work was proportionate (draft plus a quick reread). FAIL if the agent performed the full substantial-doc process for one comment." + } + ] + } + ] +} diff --git a/skills/writing-technical-docs/evals/fixtures/docblock-comment-scale/config.ts b/skills/writing-technical-docs/evals/fixtures/docblock-comment-scale/config.ts new file mode 100644 index 0000000..4420c83 --- /dev/null +++ b/skills/writing-technical-docs/evals/fixtures/docblock-comment-scale/config.ts @@ -0,0 +1,21 @@ +export interface Config { + delimiter: string; + pretty: boolean; + maxRows: number; +} + +export function parseConfig( + args: string[], + env: Record, +): Config { + const delimiter = + flagValue(args, "--delimiter") ?? env.CSV2JSON_DELIMITER ?? ","; + const pretty = args.includes("--pretty"); + const maxRows = Number(flagValue(args, "--max-rows") ?? "10000"); + return { delimiter, pretty, maxRows }; +} + +function flagValue(args: string[], name: string): string | undefined { + const index = args.indexOf(name); + return index === -1 ? undefined : args[index + 1]; +} diff --git a/skills/writing-technical-docs/references/doc-types.md b/skills/writing-technical-docs/references/doc-types.md new file mode 100644 index 0000000..6af4015 --- /dev/null +++ b/skills/writing-technical-docs/references/doc-types.md @@ -0,0 +1,103 @@ +# Doc types: structure and audience defaults + +Each doc type has a conventional structure its readers already expect. When your doc +matches a type here, the structure step of the writing process is done — use the +convention and spend your effort on content. Only invent a structure when no type fits. + +**Evergreen** marks how strictly the timeless-content rules apply (see +[style-principles.md](style-principles.md)): *strict* docs are re-read for months or +years and must not narrate the moment of writing; *relaxed* docs are anchored to an +event but their lasting parts should still stand alone. + +## Doc-block comment (function / class / module docs) + +- **Audience:** a developer calling or extending this code, reading in an editor + tooltip or generated reference. +- **Structure:** one-sentence summary (the essential fact — tooltips show only this) → + behavior and contract details → parameters → return value → errors/exceptions → + example if it earns its lines. +- **Evergreen:** strict. No "now handles", "no longer", "after the refactor" — describe + what the code does. +- Follow the language's doc conventions (JSDoc, docstrings, rustdoc). Parameter, + boolean, default, return, and deprecation phrasing: see + [formatting.md](formatting.md#api-reference-comments). + +## Inline comment + +- **Audience:** the next developer editing this code. +- **Structure:** none — a comment this small skips the process. Write it directly. +- **Evergreen:** strict. Explain *why*: non-obvious constraints, deliberate departures, + algorithms. Never restate the next line, and never narrate history ("// moved from + parser.ts", "// workaround until #1234 lands" — link the issue if it's load-bearing, + else delete). + +## Commit message + +- **Audience:** a future archaeologist running `git log` / `git blame` to understand + why this change exists. +- **Structure:** subject line in the imperative, ~50 characters ("Fix race in cache + invalidation") → blank line → body wrapped ~72: what changed and *why*, not a diff + restatement → trailers (issue links, co-authors) per repo convention. +- **Evergreen:** relaxed. The commit is a historical record, but the *why* must make + sense years later without the session's context. + +## PR description + +- **Audience:** reviewers — teammates with full context, or maintainers seeing your + work for the first time. Judge which, and front-load context for the second group. +- **Structure:** what and why (linked issue) → how, at the level a reviewer needs → + how it was verified → anything you're unsure about or want eyes on. +- **Evergreen:** relaxed — a PR is anchored to a moment. But the "why" gets quoted into + merge commits and dug up later; write it to stand alone. + +## Review comment + +- **Audience:** the change's author, who must act on it. +- **Structure:** none conventional; one point per comment. Say what you see, why it + matters, and what would resolve it — a question when you're unsure, a request when + you're not. +- **Evergreen:** relaxed. Tone carries the doc: direct about the code, never about the + author. + +## README + +- **Audience:** a first-time evaluator deciding whether to use the project, then a new + user trying to get running. Optimized for scanning. +- **Structure:** what it is (one paragraph, no marketing) → quickstart / install → + core usage → where to go deeper (links to docs, contributing, license). Badges and + demos only where they help the evaluator. +- **Evergreen:** strict. "New in 2.0" belongs in release notes; the README describes + the project as it is. + +## Design doc / RFC + +- **Audience:** peers who must understand, challenge, and later implement the design. +- **Structure:** problem and context → goals and non-goals → proposal → alternatives + considered and why they lose → open questions. +- **Evergreen:** strict for the design description; the *decision record* part (what + was decided, when, and why) is legitimately dated — label it as a decision, don't + weave it into the description of the system. + +## Release notes / changelog + +- **Audience:** existing users deciding whether to upgrade and what changed for them. +- **Structure:** per version: breaking changes → features → fixes, each entry linking + its change. +- **Evergreen:** this is the time-stamped genre — dates and versions are the point. + Entries still describe changes factually ("Add support for X"), not breathlessly + ("The long-awaited X is finally here!"). + +## Skill document (SKILL.md and references) + +- **Structure owned elsewhere:** `slow-powers:writing-skills` is the doc-type + authority for skills — frontmatter, description rules, body structure, and + skill-specific prose conventions. Load it before authoring or editing a skill. +- The style principles still apply to skill prose where writing-skills is silent; + on any conflict, writing-skills wins. + +## Sources + +Type conventions synthesized from common developer practice, with API-comment phrasing +adapted from the +[Google developer documentation style guide](https://developers.google.com/style) +(CC BY 4.0). diff --git a/skills/writing-technical-docs/references/formatting.md b/skills/writing-technical-docs/references/formatting.md new file mode 100644 index 0000000..e64a3e1 --- /dev/null +++ b/skills/writing-technical-docs/references/formatting.md @@ -0,0 +1,175 @@ +# Formatting technical content + +A lookup reference for how to format particular content types in developer docs. +Consult it when one of these content types appears in a doc you're drafting, and during +review to verify the draft against it. Don't read it front to back. + +Project or venue conventions (a repo's existing docs, a platform's comment syntax) +outrank everything here. + +## Headings + +- Sentence case ("Migrate the database", not "Migrate the Database"). +- Task-based sections get a bare-infinitive heading ("Create an instance"); conceptual + sections get a noun phrase that doesn't start with an -ing verb ("Migration + concepts", not "Migrating"). +- One unique H1 per page; don't skip levels (H2 under H1, H3 under H2); every heading + is followed by content before the next heading. +- Introduce a group of subsections with "The following sections ...", not the ambiguous + "this section". +- Prefix a section that applies only in some scenarios with "Optional:". + +## Lists + +- **Numbered** when sequence matters (steps, priorities); **bulleted** when it doesn't + (options, examples) — and make clear whether every item applies. **Description + lists** for term/definition pairs. +- Never a one-item list; fold it into prose or use other formatting. +- Keep items parallel: same grammatical form, same capitalization and punctuation + scheme within a list. +- Introduce a list with a complete sentence: colon if the list follows immediately, + period if something intervenes. Don't introduce with a partial sentence the items + complete. +- In running text, use serial commas and never end a list with "etc." — if the list + isn't exhaustive, say so in the lead-in ("processes data such as ..."). + +## Tables + +- Use a table when each item has three or more related fields (name, type, + description); pairs belong in a description list; single values in a list. +- Sentence-case, concise column heads with no trailing punctuation. Sort rows + logically, or alphabetically when there's no logical order. +- Never use tables for page layout or to frame code snippets. One-column tables become + lists; long or multi-header tables get split. +- Introduce each table with a sentence and keep it adjacent to the text that refers to + it. + +## Procedures + +- One action per numbered step, imperative mood, parallel openings. Combine menu paths + with `>` ("Click **File > Open**"). +- The intro sentence adds context the heading doesn't already give — if the heading + says it, skip the intro. A single-step procedure is a bullet, not a numbered list. +- Prefix conditional steps with "Optional:". For repeated procedures, reference the + canonical one instead of copying it. +- No directional language ("the button below", "in the above diagram") — it breaks with + layout changes and screen readers. Name the element instead. +- Introduce a command by what it does ("Deploy the load generator:"), not with "Run the + following command:". +- When several ways exist to do something, document the best one. + +## Notices (Note / Caution / Warning) + +- **Note**: useful but not critical — the reader succeeds without it. **Caution**: + proceed carefully. **Warning**: "don't do this" — irreversible actions, data loss, + security risk. +- Use sparingly and never stack two in a row; overuse makes readers skip all of them. + If unsure, write the point as regular text first and promote it only if it truly sits + outside the flow. +- Never put prerequisites, essential steps, or expected results in a notice — that + content belongs in the main flow. Never use a notice for a cross-reference. + +## Code in text + +- Code font (backticks) for anything the reader could mistake for prose: class, method, + variable, and attribute names; commands and their output; data types; language + keywords; filenames; placeholder variables; HTTP methods and status codes. +- Not code font: product and service names, domain names, URLs the reader visits. +- When a word is both a code element and a concept, code font marks the element + ("the `Activity` class") and plain text the concept ("an activity's lifecycle"). +- Don't bend code into grammar: avoid pluralizing or possessivizing code-font items + (reword instead of writing "`endpoint`s"). +- Link an API element to its reference entry on first use; very common classes don't + need repeated links. + +## Code samples + +- Follow the language's own style guide for indentation and layout; wrap lines around + 80 characters so samples survive narrow windows and print. +- Mark omitted code with a comment in the sample's language ("# Several lines omitted + here"), never with "..." or "…". +- Introduce each sample with a sentence — colon when the sample follows immediately, + period when something intervenes. +- Samples should run as shown. Keep them minimal but complete: one excellent, + realistic example beats several sketchy ones. + +## Commands and placeholders + +- Link the command's reference documentation where you introduce it; document only the + arguments the task needs and let the reference carry the full list. +- Prefer a click-to-copy example that runs unedited. Keep `[]`, `{}`, `|`, and `...` + meta-syntax out of copyable blocks — it breaks when pasted. +- Follow the tool's own terminology: POSIX command lines have *options* and + *arguments*, not "flags". +- Placeholders are descriptive and styled distinctly (UPPERCASE_WITH_UNDERSCORES in + code font): `PROJECT_ID`, never a bare `x` or `xxx` (except where the standard uses + it, like `2xx` status codes). Explain every placeholder on first use; with several, + list them in order of appearance with descriptions. +- Don't casually document destructive shortcuts (`--force`, `-y`, `--assumeyes`) + without a warning about what they skip. + +## UI elements and keyboard input + +- Refer to UI elements by their exact visible label in **bold**, sentence case: + "Click **Create bucket**." Don't use code font for UI labels, and don't make an + element's name a verb. +- State instructions as goals when the UI is obvious ("Refresh the page"); name the + widget only when the reader needs it. +- Verbs: **click** buttons/links/menu items, **select** checkboxes and list items, + **enter** or **type** text, **press** keys, **turn on/off** toggles. +- Prepositions: *in* dialogs, fields, lists, menus, panes, windows; *on* pages, tabs, + toolbars. +- Keyboard: spell out modifier names (Control, Command, Shift — not symbols), use + `Modifier+Key` ("Press Control+C"), and give the macOS variant in parentheses after + the Windows/Linux one. + +## API reference comments + +- Document every public class, method, constant, field, parameter, return value, and + thrown exception. The first sentence of each description is the summary — put the + essential fact there, because indexes and tooltips show only that. +- Class descriptions state purpose without repeating the class name; method + descriptions lead with the action verb ("Creates", "Returns", "Deletes"). +- Boolean parameters: "If true, validates the certificate. If false, ..." — or for + state rather than commands, "True if the zoom is set; false otherwise." +- Give each value's behavior, then the default: end with "Default: ...". +- Return descriptions stay brief and start with "The ..." ("The bird specified by the + given ID."); detail belongs in the class or method description. +- Deprecations name the replacement and what to do instead ("Deprecated. Use + `CameraPose` instead."), plus the version that deprecated it when versions exist. + +## Filenames and file types + +- Refer to filenames in code font with the word "file" ("In the `build.sh` file, ..."), + spelled exactly as on disk even when the name breaks conventions. +- Refer to file *types* by their formal name, not the extension: "a PNG file", not "a + .png file"; "a YAML file", not "a .yaml file". +- Don't verb file types: "Extract a zip file", not "Unzip a zip file". + +## Links and cross-references + +- Links point to *additional* information, never to vital information the reader needs + for the task at hand — put the essentials on the page, then link for depth. +- Short context beats a link: define the term or give the two steps inline instead of + sending the reader away. +- Be selective: every link is a decision and an exit. A couple per paragraph at most, + none in headings, and no duplicate links to the same target on one page. +- Link text describes the destination ("see Performance comparison"), never "click + here", and carries no quotation marks. + +## Dates, times, numbers + +- Dates in words ("January 19, 2017"); if numeric-only is required, use ISO 8601 + (`2017-04-15`). Date before time. Avoid seasons — name months or quarters. +- Spell out zero through nine and numbers opening a sentence; numerals for 10 and up, + and always for technical quantities, versions, measurements, and percentages + ("5 MB", "version 3", "8%"). Commas in numbers with four or more digits ("1,532"). +- Spell out ordinals ("first", not "1st"); dimensions take a lowercase x ("192x192"). + +## Sources + +Adapted from the +[Google developer documentation style guide](https://developers.google.com/style) +(CC BY 4.0) and the +[Red Hat Technical Writing Style Guide](https://stylepedia.net/style/) +(CC BY-SA 3.0), trimmed to what professional developers actually format day to day. diff --git a/skills/writing-technical-docs/references/style-principles.md b/skills/writing-technical-docs/references/style-principles.md new file mode 100644 index 0000000..6a9f2d0 --- /dev/null +++ b/skills/writing-technical-docs/references/style-principles.md @@ -0,0 +1,128 @@ +# Style principles for technical docs + +Condensed, evergreen writing guidance for professional software developers, distilled +from the sources listed at the bottom. Read this when you need a decision grounded — +during drafting when a style question comes up, and during review when something reads +wrong. Do not read it cover-to-cover before drafting; most of it confirms what you +already do. + +## Audience and style come first + +Before writing anything, decide two things. Every later choice — structure, depth, +terminology, tone — is checked against them: + +- **Audience:** who reads this, and what do they already know? A beginner following a + quickstart, an expert looking up a flag, a teammate reviewing your design, and a + maintainer seeing your PR for the first time need different docs. For anything longer + than a page, say who the doc is for in an explicit audience sentence near the top. +- **Style:** what register fits the doc type and venue? A README, a design doc, and a + review comment have different defaults (see [doc-types.md](doc-types.md)). + +When a writing decision is hard, re-ask the audience question: *is this right for the +person who will actually read it?* If the answer is clear, you have your answer. + +## Voice and tone + +- Conversational, friendly, respectful — a knowledgeable colleague, not a marketing page + and not a spec committee. Neither slangy nor stiff. +- Don't perform enthusiasm or humor; don't be deliberately dry either. The doc's job is + to give someone in a hurry the information they came for. +- Skip "please" in instructions: "To view the document, click **View**", not "please + click". +- Avoid buzzwords, figurative language, and culture-specific references (sports, + holidays, idioms) — they confuse global readers and date the doc. + +## Clarity and concision + +The always-rules, cheap to apply at any scale: + +- Say it directly. Don't use a paragraph where a sentence works. +- One idea per paragraph; break walls of text up. +- Write processes sequentially — never reorder steps for narrative effect. +- Define acronyms and abbreviations on first use; avoid coining new ones. +- Use formatting (headings, lists, tables, code font) to make the doc scannable — see + [formatting.md](formatting.md). +- Writing for beginners? Name the problems they'll hit and the things they'll overlook. + Anticipating confusion is what makes a beginner doc good. + +## Sentence-level defaults + +- **Active voice by default** — make the doer the subject: "Send a query to the service. + The server sends an acknowledgment." Passive voice is acceptable when the object + matters more than the actor ("The file is saved"), when the actor should be + de-emphasized ("Over 50 conflicts were found in the file"), or when the actor is + irrelevant. +- **Present tense** for general behavior: "the server sends", not "the server will + send". Reserve *will* for events that genuinely happen later (asynchronous delivery, + a file archived at the next backup run). Never use hypothetical *would* ("the server + would then remove you") — commit to what happens. +- **Second person** for the reader: "you", not "we". Use the imperative for + instructions ("Click **Submit**"). Use third person for what the software or an end + user does. Reserve *user* for the user of the software your reader is building. +- **Condition or goal before instruction**: "To delete the entire document, click + **Delete**" — the reader can skip the instruction when it doesn't apply. Same pattern + for references: "For more information, see X", not "See X for more information". +- Keep sentences short and words simple. Avoid noun stacks longer than three words + ("default printer configuration parameters" forces the reader to parse the + relationships). Use the same term for the same thing throughout. + +## Timeless (evergreen) documentation + +Documentation is read long after it's written. Write for the current state of things, +not the moment of writing. Avoid words and phrases that anchor the doc to a point in +time or assume knowledge of earlier versions: + +> as of this writing · currently · does not yet · eventually · existing · future / +> in the future · latest · new / newer · now · old / older · presently · soon + +- These are implied by the doc existing at all ("currently supported" is just + "supported"), or they rot within months ("soon", "latest"). +- Time-stamped genres are legitimate exceptions: release notes, changelogs, blog posts, + and deprecation notices are *about* points in time. PR descriptions and commit + messages carry session context by design — but even there, write the parts that will + be re-read (the "why") so they stand alone later. +- If you must mark something as new, anchor it: "The January 14, 2021 release includes + a new resource panel" ages well; "the new resource panel" doesn't. +- **The agent-specific failure mode:** narrating the work session. "I moved this into + `utils.ts`", "this now handles retries", "the old parser used to..." — all of these + describe the edit, not the system. Describe the system. +- Don't document unreleased or planned features as if they exist, and don't promise + them ("will support", "eventually"). + +## Claims and recommendations + +- No excessive claims: nothing about performance, cost, or security that the reader + can't verify or that a future incident could invalidate. Avoid superlatives + (*best*, *fastest*, *simplest*) and absolutes (*never*, *always*); use *ensure* and + *guarantee* only when literally true. +- Security claims age worst. "Helps prevent account takeovers" survives a breach; + "prevents account takeovers" doesn't. +- If you state numbers (performance, storage, cost), cite the source or measurement. +- Compare factually: "distributes computation in memory, so it can be faster for this + scenario — see [benchmark]" beats "faster than X". +- Make recommendations in an active voice with an owner: "We recommend creating multiple + service accounts", not "It is recommended to create...". + +## Jargon, global readers, inclusion + +- Jargon: write around it if you can ("when the project finishes, review what worked" + instead of "hold a post-mortem"); replace it with a plainer term if one exists; + otherwise define it in plain language on first use or link a trusted definition. + Jargon that names a code element stays only in direct references to that element. +- Global audience: short unambiguous sentences, consistent terminology and formatting, + no idioms, no humor that must be translated, no seasons ("in November", not "in + winter"). +- Inclusive language: avoid gendered terms ("man-hours" → "person-hours"), ableist + metaphors ("sanity check" → "validity check"), and violent figures of speech. Use a + diverse set of names in examples. + +## Sources + +Adapted for agent-authored developer documentation from the +[Google developer documentation style guide](https://developers.google.com/style) +(CC BY 4.0), the +[Red Hat Technical Writing Style Guide](https://stylepedia.net/style/) +(CC BY-SA 3.0), and +*[A Guide to Technical Writing: Dos & Don'ts](https://medium.com/shecodeafrica/a-guide-to-technical-writing-7efcd0e70166)* +(Olamide Makinde). When a detail here seems wrong for your venue, the sources are the +tiebreaker — and your project's own conventions outrank them.