Skip to content

Worked examples

The prose that lives in your codebase.

READMEs. API docs. PR descriptions. Design docs. Runbooks. Changelogs. ContentRX reviews the prose that lives in your repo, against one opinionated editorial standard, before it merges.
Six examples below. Each is real writing under time pressure, the cleaned rewrite, and why each flag fired. Calibrated for the prose that ships in a codebase.

README

Repo entry point

The first file anyone, or any agent, opens. It gets written by the person who knows the system best, which is exactly why it leaves out the things they already know.

What you wrote

# orbit Internal service for tenant routing. Wraps the edge config and the tenant DB. See the RFC for background. Run `make dev` (needs the usual env from 1Password). Most things you'll touch are in `internal/router/`. Ping #orbit if stuck.

Suggested rewrite

# orbit orbit maps each incoming request to a tenant and region before it reaches the app. It wraps the edge config and the tenant DB. ## Run it cp .env.example .env # values in 1Password, Eng vault, 'orbit' make dev curl localhost:8080/healthz # {"ok":true} means you're good Background: docs/rfcs/0007-tenant-routing.md. Code you'll usually touch: internal/router/. Stuck: #orbit.

3 flags applied· 2 worth adjusting· 1 quick polishSee the per-flag reasoning
  • Worth adjusting✦ AIClarity

    The first line assumes the reader already knows what tenant routing decides here. Someone cloning this cold cannot tell what orbit is for before reading an RFC that isn't linked.

    Suggested

    Add one sentence of what it decides. 'orbit maps each incoming request to a tenant and region before it reaches the app.' Keep the rest, the terse register is fine.

  • Worth adjusting✦ AISpecific reference

    'The RFC', 'the usual env', and '#orbit' each point somewhere only a current teammate can follow. The reader who needs the README most is the one who doesn't have those.

    Suggested

    Link the RFC by path. Name the env file or bootstrap command. The Slack channel is a fine backstop, not the setup path.

  • Quick polish✦ AIVoice and tone

    'Most things you'll touch are in internal/router/' is true for you today and dates fast, and it still doesn't give a first run.

    Suggested

    One command that returns something proves the clone works and carries more than the orientation. Drop 'most things'.

API reference

Endpoint doc

Reference docs get written right after the endpoint ships, by the person who just built it. They document what they're looking at, the success path, and skip the parts that were obvious while their hands were on the code.

What you wrote

### POST /v1/exports Starts an export job for the caller's workspace. Pass `format` (`csv` or `json`) and an optional `since` ISO timestamp. Returns the job id. Poll `GET /v1/exports/{id}` for status.

Suggested rewrite

### POST /v1/exports Auth: API key in the Authorization header. Starts an async export job for the caller's workspace. Body: `format` (`csv` or `json`, required), `since` (ISO timestamp, optional). Returns 202 with `{"id": "exp_…"}`. A bad `format` returns 422 with `{"error": "format must be csv or json"}`. Poll `GET /v1/exports/{id}` every 5s. Status is queued, running, done, or failed. No callback is sent.

3 flags applied· 2 worth adjusting· 1 quick polishSee the per-flag reasoning
  • Worth adjusting✦ AICompleteness

    The success path is documented. The integrator's first real questions aren't. What auth does this need, what does a rejected request return, and is the job async with no callback. They hit those before they hit the happy path.

    Suggested

    Add the auth line, one example error body, and a sentence that the job is async so the caller knows to poll.

  • Worth adjusting✦ AIClarity

    'Returns the job id' in what shape. A bare string, a JSON object, a Location header. The integrator has to guess or read your source, which is the thing the doc exists to prevent.

    Suggested

    Show the actual response. 'Returns 202 with {"id": "exp_…"}.'

  • Quick polish✦ AISpecificity

    'Poll for status' has no interval and no terminal states, so every caller invents their own.

    Suggested

    'Poll every 5s. Status is queued, running, done, or failed.' One sentence, one fewer support thread.

PR description

Before merge

The description gets written last, when the work is done and you're tired and the next thing is waiting. So it gets the summary the author can write from memory, not the one the reviewer needs to review it.

What you wrote

Fixes the flaky checkout test and tightens the retry logic while I was in there. Also bumped the timeout. Should be good now, tested locally.

Suggested rewrite

The checkout test was flaky because it asserted on order state before the webhook settled. Now it waits on the webhook instead of a fixed sleep. While there: retry logic was retrying on 4xx too. Now it retries 5xx and timeouts only. Timeout 5s to 15s because the payment sandbox p95 is 8s and we were timing out legitimate calls. Ran the checkout suite 50x, green. Didn't touch unrelated payment paths.

3 flags applied· 2 worth adjusting· 1 quick polishSee the per-flag reasoning
  • Worth adjusting✦ AIReviewability

    A reviewer approves the reasoning, not the diff. 'Tightens the retry logic' and 'bumped the timeout' say what changed but not what was wrong or why this fixes it, so they either re-derive it from the diff or rubber-stamp it.

    Suggested

    One line of root cause per change. What made the test flaky, and what the retry logic was doing that it shouldn't.

  • Worth adjusting✦ AIClarity

    'Should be good now' and 'tested locally' carry your confidence but not your evidence. The reviewer can't tell if 'tested locally' was the one test 50 times or the full suite once.

    Suggested

    Say what you ran and what it covered. The reviewer is deciding how hard to look, and that line tells them.

  • Quick polish✦ AIScope

    Two unrelated changes in one description make the rollback story ambiguous if one of them regresses later.

    Suggested

    A line each, or note they're coupled and why, so a future bisect knows what it's looking at.

Design doc

Before the build

A design doc written by someone who did the thinking and wants the reader to see the path they took. The proposal is in there, after a few paragraphs of the context they can't quite bring themselves to cut.

What you wrote

## Background Over the last two quarters we've seen growth in multi-region usage, and the current single-region session store has come up repeatedly in incident reviews and planning. There are a number of considerations here, including latency, failover behavior, and operational surface. This document walks through the history and the options we weighed before arriving at a recommendation. ## History The session store was originally built for a single region because at the time...

Suggested rewrite

## Proposal Move the session store to a per-region primary with async cross-region replication. One reason above the others: every multi-region incident this quarter traced to cross-region session reads at p99. ## Options weighed Global store with read replicas (rejected: replica lag still bit us on failover). Sticky regional routing (rejected: breaks on region drain). Per-region primary (proposed). ## Background The single-region store was right when there was one region...

3 flags applied· 2 worth adjusting· 1 quick polishSee the per-flag reasoning
  • Worth adjusting✦ AILead with the decision

    The reader opening a design doc needs the proposal first, what you want to do and the one reason it's right. The history matters, but a reviewer who has to mine three paragraphs for the recommendation reviews the writing, not the decision.

    Suggested

    Open with a Proposal section. Move Background and History below it as the support they are.

  • Worth adjusting✦ AIClarity

    'A number of considerations' and 'the options we weighed' name that tradeoffs exist without naming them. The doc's job is the tradeoff itself, not the fact that there was one.

    Suggested

    State the considerations as the actual tension. 'Per-region primaries cut p99 but make failover a manual call.'

  • Quick polish✦ AIReviewability

    No stated alternative and no why-not. A doc that only presents the chosen path reads as a decision already made, which makes the review theater.

    Suggested

    One paragraph on the option you rejected and the reason. It's what makes the review real.

Runbook

On-call

Runbook steps get written during or right after the incident, by the person who just fixed it. It's exact in their head. On the page it's exact only if you were there too.

What you wrote

### If the queue backs up Check the consumer lag dashboard. If it's high, the workers are probably stuck again. Restart them the usual way and keep an eye on it. If that doesn't help, escalate to the platform team.

Suggested rewrite

### If the queue backs up 1. Open the consumer-lag dashboard. Trigger: lag over 50k messages, or rising for more than 5 min. 2. Restart the workers: `kubectl rollout restart deploy/queue-worker -n prod`. 3. Lag should fall within 5 min. If it isn't falling by then, page #platform-oncall (PagerDuty service 'queue') with the dashboard link.

3 flags applied· 2 worth adjusting· 1 quick polishSee the per-flag reasoning
  • Worth adjusting✦ AISpecificity

    The next on-call doesn't know what 'high' is, what 'the usual way' restarts, or how long to watch before escalating. A runbook is read by the person who wasn't there, and every judgment word it leaves in is a call they make at 3am without you.

    Suggested

    Replace each judgment word with the number you actually used. The threshold, the command, the wait.

  • Worth adjusting✦ AIClarity

    'The workers are probably stuck again' references a past incident the reader may not have lived through. Name the symptom that confirms it, not the memory of last time.

    Suggested

    State what 'stuck' looks like on the dashboard so the reader can confirm it themselves.

  • Quick polish✦ AISpecificity

    'Keep an eye on it' and 'if that doesn't help' have no threshold, so the reader can't tell when to stop waiting.

    Suggested

    Give it a clock. 'Lag should fall within 5 min. If it isn't falling by then, escalate.'

Changelog

Release notes

Release notes get written under the release, from the merge list, by someone who knows what each line did and is compressing fast. The compression is where the reader loses the one change that affects them.

What you wrote

## v2.4.0 - Performance improvements to the sync engine - Fixed several edge cases in auth - Various dependency updates - Minor UI polish

Suggested rewrite

## v2.4.0 - Sync batches writes in 200-record chunks (was per-record). No API change. Large syncs are ~4x faster. - Auth: expired refresh tokens now return 401 instead of 500. If you retried on 500, that path no longer fires. - Dropped Node 16 support. Minimum is now Node 18. - Settings: moved 'Danger zone' below the fold so it isn't the first thing your cursor lands on.

3 flags applied· 2 worth adjusting· 1 quick polishSee the per-flag reasoning
  • Worth adjusting✦ AIReader impact

    A changelog answers one question, does this release change something I rely on. 'Fixed several edge cases in auth' can't be acted on. The person whose login flow just changed needs to see that line and recognize it as theirs.

    Suggested

    Write each line so the affected reader recognizes it. Name the behavior that changed, not the category it was in.

  • Worth adjusting✦ AIClarity

    'Performance improvements to the sync engine' is the result, not the change. If sync now batches differently or a default moved, that's the line. The speedup is the consequence.

    Suggested

    Lead with what changed, then the effect. 'Sync batches writes in 200-record chunks, large syncs ~4x faster.'

  • Quick polish✦ AIReader impact

    'Various dependency updates' hides whether any of them are breaking.

    Suggested

    One sub-line for anything that moves a minimum version or a default. It earns the reader's trust in the rest of the list.