Skip to content
124 changes: 124 additions & 0 deletions .agents/references/content-design-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Content design plan

Before we begin drafting a docs page, we need to be extremely clear on its purpose, value, and audience. We define these things by completing a content design plan before making any changes to the docs.

Read this after a change has passed `.agents/references/docs-worthiness-criteria.md`, and before opening any template. Every new page and every substantive update to an existing page needs a content design plan — whether the drafting is done by a scheduled agent or by a person invoking a drafting skill directly.

## Why this step exists

Drafting that starts at the template produces pages shaped by the template. The scaffold has a "Key features" section, so the draft gets a key features list; it has a "How it works" section, so the draft explains how it works — whether or not any reader needed either.

The plan inverts that. Start by determining who the reader is and what they are trying to do, and the content type falls out of the answer instead of dictating it.

That benefit does not depend on when a human reads the plan. Writing it is what shapes the draft.

**What the plan is for depends on where it is reviewed**, and the two cases are genuinely different:

- **Interactive drafting — a real checkpoint.** When a person invoked the drafting skill, present the plan and wait before writing any prose. Here the plan is cheap to disagree with: redirecting the audience or the content type costs a conversation instead of a rewrite. `write-feature-docs` already works this way with its Step 3 outline confirmation.
- **Automated runs — a record and a consistency check.** A scheduled run opens a draft PR without a pre-draft checkpoint, so by the time anyone reads the plan the prose exists. It is not saving the reviewer a rewrite. What it does is make the reasoning inspectable next to the diff, so a reviewer can catch drift — the plan says "backend engineer configuring self-hosted GitLab" and the page reads like a conceptual overview — and can reject on aim rather than on prose.

Do not claim the automated path buys early disagreement. It does not, and pretending otherwise obscures a real tradeoff: the pipeline was deliberately built to open draft PRs rather than propose first, accepting late review in exchange for not gating every candidate on a human.

## Principles

These come from [GitHub's content design principles](https://docs.github.com/en/contributing/writing-for-github-docs/content-design-principles), which we follow.

- **Create just enough docs.** More content makes everything harder to find, and anything added dilutes everything else. Adding a page has a cost paid by every other page.
- **Document high-impact, high-value scenarios** rather than attempting to comprehensively cover every possible use case. Completeness is not the goal; usefulness is.
- **Prioritize clarity, meaning, correctness, and consistency**, in that order.
- **Decide based on what people are trying to do**, not on what is technically correct or structurally tidy. When a style or structure question is genuinely open, resolve it by asking what best supports the reader's goal.
- **Be user-centered and inclusive.** Respect everyone who visits the docs and make content that works for them.

## Required fields

Fill in every field. "Not applicable" is a valid answer only with a reason.

### Target audience and their JTBD

Who is this for, and what job are they trying to get done?

Name a specific reader in a specific situation, not a demographic. The job is what they are trying to accomplish in their own terms — the outcome they want, not the feature they will use to get it.

- ✅ "A backend engineer setting up their team's first cloud agent, who needs it to reach a private GitLab instance and has not configured Warp credentials before."
- ❌ "Developers who use cloud agents."

If you cannot describe a reader arriving at this page with a problem, that is a signal the page should not exist. Go back to the worthiness criteria.

### Problem statement

What specific difficulty does the reader hit without this doc?

Describe the failure: what they try, where it breaks down, and what it costs them. If the honest answer is "nothing, they just would not know this exists," the change probably failed the worthiness gates and should not have reached this step.

### Goals

What can the reader do after reading it?

Write these as reader capabilities, not page contents. "The reader can decide which credential strategy fits their setup and configure it" is a goal. "Explains the credential strategy options" is a table of contents entry.

Two or three goals. More than that usually means the page is doing several jobs and should be split.

### Purpose and value added

Why does this page earn its place, and what is lost if it does not exist?

This is the "just enough docs" test applied to this specific page. If the value is already delivered by an existing page, the answer is to update that page — go back to the worthiness criteria and pick the update outcome instead.

### Content type and model

Which content type, and why?

Name the type and give a one-line rationale tied to the reader's job. See the "Drafting by content type" section of `AGENTS.md` for the full definitions and rules.

The type should follow from the JTBD:

- Reader is learning what something is → **conceptual**
- Reader is performing a task → **procedural**
- Reader is looking something up mid-task → **reference**
- Reader is stuck on a specific failure → **troubleshooting**
- Reader wants the fastest path to a working result → **quickstart**
- Reader needs both the concept and the task in one place → **feature documentation (combined)**

If two types fit equally well, the reader's job is probably ambiguous. Resolve that before drafting.

### Skills and templates to use

Name the specific drafting skill and the specific template file.

Being explicit here catches type/template mismatches before drafting rather than in review, and it makes the plan reproducible — a reviewer can check that the draft actually used what the plan chose.

### High-impact scenarios

Which core user tasks does this cover, and which edge cases are deliberately excluded?

List the scenarios worth covering, in priority order. Then **name what you are leaving out and why.** The exclusions are the load-bearing half of this field: they are what keeps the page from growing to cover every configuration permutation someone might hit.

- ✅ "Covers: self-hosted GitLab with a personal access token; GitLab.com with OAuth. Excludes: self-managed GitLab behind a corporate proxy — rare, and the proxy configuration is the user's own infrastructure concern, not ours."
- ❌ "Covers all GitLab setups."

## Where the plan lives

Fill in `.agents/templates/content-design-plan.md`, then:

- **Present it to the requester before drafting** when a person invoked the drafting skill. This is the checkpoint, and skipping it forfeits the only cheap chance to redirect.
- **Include it in the PR body** as a `## Content design plan` section, in every case. A plan that lives only in an agent run log is not reviewable in practice — nobody opens the run to check the reasoning behind a page.

For an update to an existing page rather than a new page, the same fields apply, scoped to the change: the audience and job for the section being added or revised, and what the page fails to do for that reader today.

## When a plan can be skipped

Small corrections do not need one. Skip the plan for:

- Typo, grammar, link, and formatting fixes
- Terminology sweeps that do not change meaning
- Mechanical or generated updates (changelog entries, OpenAPI spec sync, snapshot and bookkeeping refreshes)
- Screenshot replacements

If the change adds, removes, or reframes information a reader acts on, it needs a plan. If in doubt, write one — it is four sentences.

## Related references

- `.agents/templates/content-design-plan.md` — the fill-in artifact this reference explains
- `.agents/references/docs-worthiness-criteria.md` — whether the doc should exist, applied before this
- `AGENTS.md` → "Drafting by content type" — the content type definitions and rules
- `.agents/templates/` — the page scaffolds
147 changes: 147 additions & 0 deletions .agents/references/docs-worthiness-criteria.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Documentation-worthiness criteria

Decide whether a shipped change should produce documentation at all.

Read this before drafting, and before proposing a doc gap as actionable. Every docs agent that can create or update a page must apply it: `missing_docs`, `draft_docs`, and any drafting skill they call.

This reference answers one question: **should this doc exist?** Once a change passes, `.agents/references/content-design-plan.md` answers the next question — what the doc should be. Never write a content design plan for a change that has not passed these gates.

## The default is no docs

Not every shipped change warrants documentation. The docs repo competes for reader attention with itself: every page added makes every other page harder to find, and a page nobody needs is a page someone still has to maintain, review, and keep accurate through the next three renames.

So the default answer is **no**, and the burden is on the change to earn a page. Do not look for a reason to document something. Look for concrete evidence that a reader will be stuck, surprised, or unable to configure something without it — and if you cannot find that evidence, the answer is no.

A changelog entry is not evidence. Neither is a merged spec, a Linear ticket, or the fact that a feature is new. Those establish that something happened, not that a reader needs help with it.

## Scope

These criteria govern the **weekly release stream** — changes that reached users in a stable release, and the continuously shipped server and platform surfaces behind them.

Major launches (Warp Factories, for example) are planned in advance and documented by the docs team on a proactive, human-led path. They do not run through these gates. If you encounter a change that is clearly part of an announced launch, defer it rather than gating it.

### How much applies depends on who is asking

**Automated runs apply the full gate.** A scheduled agent has no context beyond what it can read, and unattended drafting at scale is what this reference exists to control. Default to no docs; make the change earn the page.

**A person asking directly is subject to Gate 0 only.** Gate 0 is factual — has this shipped, is the surface public — and a requester can be wrong about it, so it is worth verifying no matter who asked. Gates 1 through 3 are judgment, and someone requesting a page usually has context an agent does not: the roadmap, the support queue, a conversation the agent was not in.

So do not decline a person's request on Gates 1-3. Raise the concern once — "an existing page already covers this," "this looks like a UI-only change" — then defer to their answer. An agent arguing with someone who knows more than it does is a worse failure than one extra page.

The gates still shape *how* you draft for a human request: they push toward updating an existing page over creating a new one, and toward naming the concrete thing a reader needs.

## Decision procedure

Work through the gates in order. Gate 0 is a hard prerequisite. Gates 1 through 3 are alternatives — passing any one is enough. Then check the disqualifiers, which override a pass on any gate.

### Gate 0 — Is it shipped and public?

A hard prerequisite. If this fails, stop.

- Is the feature GA to users, not dogfood, preview, or research preview?
- Is the surface public? The `warpdotdev/warp` client repo is public. **`warp-server` is private**, and its surfaces are not documentable until released; the exception is the public Agent API, whose released surface is exactly what is already in `developers/agent-api-openapi.yaml`.
- Is it gated behind a non-GA feature flag?

See the "Public vs. private surfaces" section of the `missing_docs` skill for the full rollout and exposure rules — this gate reuses them rather than restating them.

**Failing Gate 0 means defer, not reject.** The change may qualify later. Record it as deferred with the blocking reason so it re-surfaces when the flag goes GA or the endpoint reaches the spec. Do not draft "ready for when it ships" pages — an unreleased page that sits in a PR goes stale before it merges, and a merged one is wrong the day it publishes.

### Gate 1 — Is it configurable?

Can a user change its behavior? Name the concrete knob:

- A setting (give the `toml_path` key)
- A CLI flag or command
- An API parameter or request field
- A file-format field
- A toggle they can actually reach in the UI

If you cannot name the specific knob, this gate does not pass. "Users can configure the new behavior" is not a knob. `agents.warp_agent.profile` is a knob.

### Gate 2 — Can a user get stuck?

Either of these:

- **Error-prone setup.** A multi-step or technically detailed process where mistakes are likely — credentials, permissions, external service configuration, environment prerequisites. Name the steps.
- **A specific error message that demands a specific, different action.** Not a generic failure the user can reason about, but a message whose correct response is non-obvious. Quote the error string.

A limit or constraint qualifies here when hitting it produces a distinct failure the user must respond to differently.

### Gate 3 — Would a user be surprised?

Underlying logic changed in a way with a non-obvious user-visible effect. Typically one of:

- A default changed
- A permission or access boundary changed
- A billing or credit consequence changed
- Data handling, retention, or residency changed
- An existing workflow now behaves differently than it did before

The test is surprise, not novelty. Would a reasonable user, doing what they did last week, get a different result and not understand why?

### Disqualifiers

These override a pass on any gate. If one applies, the answer is no.

- **Pure UI affordance.** We do not document the UI. A new button, an icon change, a relocated control, a restyled panel.
- **Small and intuitive.** A reader who opens the surface would understand it in under thirty seconds without help.
- **No user-observable change.** Internal refactors, telemetry, performance work, CI, release mechanics, dependency bumps.
- **Bug fix restoring intended behavior.** The docs already describe how it is supposed to work; the fix made reality match. Document only if the docs described the broken behavior.

## Required justification

Every verdict must be recorded with a one-paragraph justification that names:

1. **The gate it passed**, or the disqualifier that stopped it.
2. **The concrete evidence** — the setting key, CLI flag, quoted error string, changed default, API field, or named setup steps.
3. **The source** — the changelog entry and PR number, or the surface and file you verified against.

**No concrete evidence means the answer is no.** A justification that restates the changelog entry in different words is not a justification. If the strongest thing you can say is "this is a new capability users should know about," the gate did not pass.

This rule exists because it is the only part of the procedure that cannot be satisfied by rephrasing. Gates can be argued into; naming a specific `toml_path` key or quoting a real error string cannot.

## Three outcomes, not two

Every passing change resolves to one of these. Choose explicitly:

1. **Update an existing page** — the default when any page already covers the surface. Prefer this. Most shipped changes are a paragraph, a row in a reference table, or a new subsection on a page that already exists.
2. **New page** — only when no existing page covers the surface and the change needs more than a section. A new page must be justified against the existing information architecture, not just against the change.
3. **No docs** — record the verdict so it is not re-litigated.

The bias toward updating is deliberate. New-page sprawl is the main way an automated pipeline degrades a docs set: each page is defensible alone, and collectively they fragment a topic across places no reader will assemble.

## Recording the verdict

Write every decision to `.agents/skills/missing_docs/references/changelog_decisions.md`, including the rejections. A decision that is not recorded gets re-proposed on the next run, and the reviewer who rejected it has to reject it again.

## Worked examples

Drawn from the `v0.2026.07.29.09.05.stable_02` changelog. These calibrate the boundary — the point is the reasoning, not the specific features.

### Passes

**Custom model endpoints can select an API schema** ([#13938](https://github.com/warpdotdev/warp/pull/13938)) — **Gate 1, update existing page.** The knob is the schema selector on a custom inference endpoint, with three named values: OpenAI Chat Completions, OpenAI Responses, and Anthropic Messages. A user configuring a custom endpoint must pick one and cannot guess which their provider expects.

**Managed secrets validated against the 128 KiB limit** ([#14219](https://github.com/warpdotdev/warp/pull/14219)) — **Gate 2, update existing page.** `MAX_SECRET_FIELD_BYTES` in `crates/managed_secrets/src/secret_value.rs` caps a secret at 128 KiB, validated at create and update time. The failure is specific, it surfaces at a different moment than the user expects, and the workaround is non-obvious. Belongs on the existing secrets page, not a new one.

**Automatic `gcloud` sign-in during GCP provider setup** ([#14132](https://github.com/warpdotdev/warp/pull/14132)) — **Gate 2, update existing page.** Provider setup is a multi-step credential flow where errors are likely, and this changes which steps the user performs.

**Vim indent and dedent operators** ([#14268](https://github.com/warpdotdev/warp/pull/14268)) — **Gate 1, update existing page.** `<` and `>` are concrete, nameable bindings, and the editor already has a reference table of supported Vim operators. This is a row in that table. It would *not* justify a new page.

**Agent execution profiles configurable from settings files** ([#14418](https://github.com/warpdotdev/warp/pull/14418)) — **Gate 1, update existing page.** Named settings-file configuration, previously unavailable to all users.

### Fails

**Replace the armadillo icon with the theme-adaptive Warp "W" logo** ([#14344](https://github.com/warpdotdev/warp/pull/14344)) — **Disqualified: pure UI affordance.** Nothing configurable, nothing to get stuck on, nothing surprising. We do not document the UI.

**Cap and expand the shared desktop toast stack** ([#14028](https://github.com/warpdotdev/warp/pull/14028)) — **Disqualified: no user-observable change requiring action.** Behavior improves on its own; the user does nothing differently.

**MCP tool confirmations show the tool and source server** ([#14298](https://github.com/warpdotdev/warp/pull/14298)) — **Disqualified: small and intuitive.** The confirmation dialog now shows more context. A reader encountering it understands it immediately.

**`agentDefaults.computerUseModel`** (docs PR [#581](https://github.com/warpdotdev/docs/pull/581)) — **Gate 0 failure: deferred, not documented.** This is the regression case. A drafting agent wrote the page and labeled it "(unreleased feature)" in the PR title, which is the gate failing out loud. An unreleased setting key is a real knob and would pass Gate 1 — but Gate 0 comes first and is a hard prerequisite. Defer with the blocking reason and re-surface it when the feature ships.

## Related references

- `.agents/references/content-design-plan.md` — what to decide once a change passes these gates
- `.agents/references/terminology.md` — canonical product terms
- `.agents/skills/missing_docs/references/changelog_decisions.md` — the recorded verdict ledger
Loading
Loading