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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?

Expand Down
9 changes: 8 additions & 1 deletion skills/verifying-development-work/references/code-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
6 changes: 6 additions & 0 deletions skills/writing-skills/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) —
Expand Down
142 changes: 142 additions & 0 deletions skills/writing-technical-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -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<br/>and style]
audience --> gather[Gather only what<br/>the doc needs]
gather --> structure{Conventional structure<br/>for this doc type?}
structure -->|yes| use[Use it — done deciding]
structure -->|no| outline[Outline; split large docs into<br/>self-contained sections]
use --> draft[Draft for the audience,<br/>evergreen]
outline --> draft
draft --> review{Doc size?}
review -->|small| spot[Reread once: evergreen,<br/>right for the reader]
review -->|large| full[Review checklist +<br/>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.
28 changes: 28 additions & 0 deletions skills/writing-technical-docs/evals/NOTES.md
Original file line number Diff line number Diff line change
@@ -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).
62 changes: 62 additions & 0 deletions skills/writing-technical-docs/evals/evals.json
Original file line number Diff line number Diff line change
@@ -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."
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface Config {
delimiter: string;
pretty: boolean;
maxRows: number;
}

export function parseConfig(
args: string[],
env: Record<string, string>,
): 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];
}
Loading
Loading