---
name: technical-writing-ste
description: Apply the PMOS-STE writing profile — the ASD-STE100 writing rules, scoped by register — when you write or rewrite text a reader must act on: a skill body, a gate or CI failure message, an MCP tool description, workspace copy, an explainer, an OKF concept, a README. Do NOT use it on argumentative text (ADRs, PRD rationale, briefs, eval verdicts, PR bodies), where graded confidence is the payload and the profile deliberately does not apply.
version: 1.0.0
owner: wawan
risk: low
category: domain
scope: read:okf, write:any-prose
---

# technical-writing-ste — Write text a reader can act on once

PMOS's output is read under load: an agent parsing a skill body, a PM reading a red CI line. This
skill carries the **PMOS-STE profile** — the [ASD-STE100](/okf/core/concepts/simplified-technical-english.md)
writing rules, bound by **register** instead of repo-wide. The scoping is the whole design. That
concept's *one-meaning trade* section is why: applied uniformly, STE deletes the graded confidence
that eval verdicts and decision records are made of.

> **Format:** three-level progressive disclosure (`SKILL-FORMAT.md`).
> **This file demonstrates the profile it defines.** The procedure below is Class A. The rationale is
> Class B. Read the two registers against each other — that contrast teaches faster than the rules do.

## Two things to know before you apply it

**PMOS adopts the writing rules, not the vocabulary control.** ASD owns the ~900-word dictionary and
grants free reproduction only to named aerospace and defense categories. PMOS is in none of them, so
the word list is neither vendored nor checkable here. **Never write that PMOS output is
"STE-compliant."** Write "PMOS-STE" and mean the writing rules only. The stronger claim is false.

**Nothing mechanical enforces this profile.** No lint runs, and no gate reads it. An advisory
`ste_lint.py` is a named follow-on, not a shipped thing. The only mechanism is that you read this and
comply, and the only check is a human at the Acceptance Gate. Treat availability as availability. A
standard that reads as enforced when it is not is a [watermelon](/okf/core/concepts/watermelon-flag.md).

## Step 1 — Classify the text. Do this first.

Ask what the reader must do with it. Derive the class from the path, not from feel.

| Class | What the reader must do | Where it lives |
|---|---|---|
| **A — instructional** | **Act**, correctly, on one reading | `skills/**` · playbooks and runbooks · gate and CI failure strings · UI copy and microcopy · tool descriptions · template usage notes |
| **B — descriptive** | **Understand**, not obey | `okf/**` concepts and references · explainers · `**/README.md` · design and data-model docs |
| **C — argumentative** | **Weigh a judgement under uncertainty** | ADRs and decision records · `planning/prd/**` · briefs · the discoveries log · eval verdicts · PR bodies |

The three classes are the rule. **The paths are your repo's, so write them down once.** In PMOS they
also cover `build-skills/**` and `okf/core/playbooks/**` (A), `planning/explainers/**` and
`planning/design/**` (B), and `pm-decisions.md` and `discoveries.md` (C). In a product repo they
cover your CLI output, your error strings and your component copy (A), and your architecture notes
(B). When a path is not on your list, ask the question in column two and add the answer to the list.

Two boundary rules. **Text the PM wrote is Class C**, whatever it is about. And the profile binds
**new and modified text only** — never rewrite an existing corpus to satisfy it.

**Done when:** you can name the class and the row that put it there.

## Step 2 — If the text is Class C, stop here.

Class C keeps four things and nothing else:

- Short sentences, where they fit.
- One topic per sentence.
- Active voice by default.
- **One term per concept** (1.11, 9.4). This is the one hard rule that binds in every class.

Then write freely.

**Why this exemption exists — read it, because the reason is the rule.** Class C's payload *is* the
hedge. "Confidence: medium", "probably", "this should be re-run before the number is quoted" — these
carry the actual content. STE has no approved way to write them: its recurring-errors list replaces
`should` and `may` with `MUST`. Apply it here and a recommendation becomes an obligation, an estimate
becomes a certainty. The text ends up **more certain than its author was**. That inverts the
[anti-optimism](/okf/core/concepts/okr-anti-optimism.md) stance PMOS reports by. The exemption is not
leniency for hard-to-constrain prose. It is the profile refusing to damage its own repo.

**Done when:** you have applied the four principles and stopped.

## Step 3 — For Class A, write to act on.

Apply these. Rule numbers point into the standard.

- **≤20 words per sentence** (5.1). Count under 8.4–8.7. Each of these counts as **one word**:
    - a number, or a number with its unit
    - an abbreviation, or an alphanumeric identifier
    - a parenthetical
    - a hyphenated word
- **One instruction per sentence** (5.2), unless the actions happen at the same time.
- **Imperative form** (5.3). Say "Run the gate", not "the gate should be run".
- **Condition first, then a comma, then the command** (5.4). "If the branch is `claude/*`, name the
  initiative in the PR body."
- **Notes inform. Notes never instruct** (5.5).
- **Active voice** (3.6). Simple verb forms only (3.2). Keep `-ing` inside a technical noun (3.5).
- **Noun clusters: three words maximum** (2.1).
- **Keep every word** (4.2). No contractions, no dropped articles.
- **Vertical lists for anything complex** (4.3).
- **No semicolons** (8.1).
- **Every pronoun resolves to one antecedent** (GR-3, GR-4). This one earns its place in agent
  instructions: an unresolvable "it" is where a run silently guesses.
- **Inclusive language** (GR-7). Use they/them when a person's pronouns are not stated.
- **Warnings carry three parts** (7.1–7.3): the risk level, the command, the consequence. Use this for
  every destructive or irreversible action.
- **One term per concept** (1.11, 9.4). Pick the term, then use only that term.

**Done when:** every sentence is ≤20 words, every instruction stands alone, and every pronoun resolves.

### A worked pair — a real gate message

From PMOS's own workflow gate (`scripts/workflow-state.js`), the `how` line for rule O4:

> **Before:** `run build-skills/explain-surface.skill in a FRESH context (not the agent that will
> write the spec), then set explainer_path:`
>
> **After:** `Run build-skills/explain-surface.skill in a fresh context. Do not use the agent that
> will write the spec. Then set explainer_path.`

One command with a prohibition buried in a parenthetical becomes three short commands. The
prohibition is now impossible to skim past. Nothing was lost.

## Step 4 — For Class B, write to be understood.

- **≤25 words per sentence** (6.3), counted the same way.
- **One topic per paragraph** (6.5). **Six sentences maximum** (6.6).
- **Give information gradually** (6.1). Let key words carry the structure (6.2).
- Carried over from Class A, unchanged:
    - **active voice** (3.6) and **≤3-word noun clusters** (2.1)
    - **no semicolons** (8.1) and **keep every word** (4.2)
    - **pronouns resolve** (GR-3, GR-4) and **inclusive language** (GR-7)
    - **one term per concept** (1.11, 9.4)
- **The imperative stays out.** Description is not instruction (section 6).

**Done when:** no sentence passes 25 words, no paragraph holds two topics or seven sentences.

### A worked pair — a real concept sentence

From [eval-driven-pm](/okf/core/concepts/eval-driven-pm.md) — 42 words, one semicolon, a nested aside:

> **Before:** "The Quality and Review gates check the work against the pre-written rubric
> mechanically; the PM's scarce attention is spent on the one question the rubric cannot answer —
> *is this the right thing?* — and on whether the rubric itself was right."
>
> **After:** "The Quality and Review gates check the work against the pre-written rubric
> mechanically. The rubric cannot answer one question: is this the right thing? The PM spends their
> scarce attention there, and on whether the rubric itself was right."

14, 13 and 18 words. The passive is gone. **State the trade honestly:** the original's aside had more
bite, and the rewrite is flatter. For reference text that price is worth paying. For an argument it is
not — which is why Class C exists.

## Step 5 — Check the register held.

Read the finished text once more and ask the one question the word counts cannot answer:

> **Did an instruction leak into descriptive text, or a hedge get flattened out of an argument?**

Two shapes answer yes. A Class B passage has turned imperative. Or a Class C sentence's "probably"
has become "must". Either one is the failure this profile exists to prevent. Fix it there.

**Done when:** the text reads in the register its class names.

## Quality bar

Before you call the text done, confirm each of these:

- The class is derived from the table, not felt.
- Class A sentences are ≤20 words. Class B sentences are ≤25. Both counted under 8.4–8.7.
- One term per concept, throughout.
- Every pronoun resolves to one antecedent.
- Class C kept its hedges.
- Nothing claims "STE compliance".

## Level 3 sub-cases

- `ste-term-map.md` — the one-term-per-concept register (1.11,
  9.4). Read it when you name a concept in **any** register, including Class C. It holds the known
  drift with its evidence, and it proposes canonical terms rather than ruling on them.
- `ste-safety-instructions.md` — not yet written. Author it on first need, mapping section 7 onto
  destructive-action warnings and confirmation copy.
