<!-- 01-principles.md -->

# Level 3 — Core Principles (Words: Rules 1.1–1.14)

Section 1 of STE-Code governs **words**: which words you may use, in which part
of speech, with which meaning, and in which form. Every other section of the
standard assumes these fourteen rules already hold.

Three gates decide whether a word is allowed in code documentation:

1. The word is **approved in the controlled terminology** (STE-Code part 2), or
2. The word is a **code-domain technical noun** (Rule 1.5 categories), or
3. The word is a **code-domain technical verb** (Rule 1.12 categories).

A word that passes no gate must be replaced, or the sentence must be
restructured so that approved words can carry the meaning.

Definitions used throughout:

- **Controlled terminology** — the STE-Code approved word list. Each entry gives
  one part of speech and one approved meaning, plus the approved verb and
  adjective forms.
- **Code-domain technical noun** — a noun term for a specified concept in
  software development, applicable to a subject field (Rule 1.5, 19 categories).
- **Code-domain technical verb** — a verb term for a specified operation or
  process in software development (Rule 1.12, 4 categories).

Rule index:

| Rule | Statement |
|------|-----------|
| 1.1 | Use words that are approved in the controlled terminology, code-domain technical nouns, or code-domain technical verbs. |
| 1.2 | Use approved words only as the specified part of speech. |
| 1.3 | Use approved words only with their approved meanings. |
| 1.4 | Use only the approved forms of verbs and adjectives. |
| 1.5 | You can use words that you can include in a code-domain technical noun category. |
| 1.6 | Use a word that is not approved only when it is a code-domain technical noun or part of one. |
| 1.7 | Do not use words that are code-domain technical nouns as verbs. |
| 1.8 | Use code-domain technical nouns that are approved in your project, company, industry, or subject field. |
| 1.9 | When you must select a code-domain technical noun, use one which is short and easy to understand. |
| 1.10 | Do not use regional, slang, or jargon words as code-domain technical nouns. |
| 1.11 | Do not use different code-domain technical nouns for the same item. |
| 1.12 | You can use verbs that you can include in a code-domain technical verb category. |
| 1.13 | Do not use code-domain technical verbs as nouns. |
| 1.14 | Use American English spelling unless other official directives tell you differently. |

---

## Rule 1.1 — Use approved words, code-domain technical nouns, or code-domain technical verbs

In code documentation, use words that are:

- approved in the project controlled terminology,
- code-domain technical nouns, or
- code-domain technical verbs.

The controlled terminology gives the words most frequently used in code
documentation. It also lists words that are **not** approved, with approved
alternatives. Your project glossary or terminology database holds the technical
nouns and technical verbs of your subject field; always check it first.

Worked vocabulary swaps:

| Do not write | Write | Why |
|---|---|---|
| execute the script | run the script | "run" is the approved verb for executing programs |
| generate the artifact | make the artifact | "make" is approved; "generate" is not |
| utilize / leverage the cache | use the cache | inflated verb |
| bootstrap / initiate the service | start the service | "start" is approved |
| configure the runtime | set the runtime behavior | "set" is approved |
| retrieve / fetch the record | get the record | "get" is approved |
| transmit the payload | send the data | "send" is approved |
| validate / verify the input | check the input | "check" is approved |
| unable to connect | cannot connect | "cannot" is approved |
| invalid / malformed data | incorrect data, data that is not correct | "correct" is the approved adjective |

Technical terms stay: `UserAuthenticator` is a code-domain technical noun,
`serialize` is a code-domain technical verb, and both are permitted although
neither is in the controlled terminology.

Examples by documentation type:

> **Non-STE (README):** To begin utilizing the build toolchain, you must first
> generate the distributable artifact, then execute the compiled binary to
> bootstrap the local development service.
>
> **STE:** Use the build tool to make the binary. Run the binary to start the
> local service.

> **Non-STE (JSDoc):** Fetches a user record. The duration in milliseconds the
> client shall await a response prior to terminating the connection attempt.
>
> **STE:** Gets a user record. The time in milliseconds that the client waits
> for a response before it stops the connection.

> **Non-STE (docstring):** Performs validation on the input data to ensure it
> conforms to the expected schema.
>
> **STE:** Checks the input data against the schema. Gives `True` when the data
> is correct and `False` when the data is not correct.

> **Non-STE (commit):** feat: implement JWT authentication middleware
>
> **STE:** feat: add JWT authentication middleware

> **Non-STE (CLI error):** Unable to establish connection to the database.
> Please verify your credentials and retry.
>
> **STE:** Cannot connect to the database. Check your credentials and try again.

Paradigm notes:

- **Object-oriented** — prose uses approved verbs (make, get, set, call, send,
  keep). Class, method, and pattern names stay as technical nouns.
- **Functional** — `map`, `fold`, `reduce`, `filter`, `compose`, and `curry` are
  code-domain technical verbs, permitted under Rule 1.12. "Pure function" is a
  compound code-domain technical noun.
- **Procedural** — each step starts with an approved imperative verb.
  "Allocate" is not approved: write "make a buffer". "Free" and "dereference"
  are code-domain technical verbs.
- **Declarative** — SQL keywords and resource kind names are technical terms.
  "Provision" is not approved (use "make" or "set up"); "orchestrate" is not
  approved (use "control" or "manage").
- **Systems** — "own", "borrow", and "move" are Rust technical verbs.
  "Dangling pointer" and "undefined behavior" are compound technical nouns
  (category 15).

---

## Rule 1.2 — Use approved words only as the specified part of speech

Each entry in the controlled terminology carries one label: verb (v), noun (n),
adjective (adj), adverb (adv), preposition (prep), conjunction (conj), pronoun
(pron), or article (art). Use the word only in that grammatical role.

- "Query" is an approved **noun**, not a verb. Write "Send a query to the
  database", not "Query the database".
- "Static" is an approved **adjective**, not a verb. Write "Make the variable
  static", not "Static the variable".
- Some words carry more than one label. "Call" is an approved verb and an
  approved noun; the position in the sentence shows the function.

If the word you want is not in the controlled terminology:

1. Find the word in a standard English dictionary.
2. Find the best synonym that is approved in the STE-Code controlled terminology.
3. Use that approved word, or write a different sentence construction.

When you replace a word, make sure that the meaning does not change. If it
changes, select a different word or restructure the sentence.

| Violating form (do not use) | Part-of-speech error | Approved replacement |
|---|---|---|
| Query the database / Cache the result / Queue the job / Log the error / Index the record | technical noun used as verb | Send a query / Keep the result in the cache / Put the job in the queue / Write the error in the log / Use the index to find the record |
| Docker the app / Git the change / Kubectl the pod / Terraform the VPC | tool name used as verb | Use Docker / Save with Git / Use `kubectl` / Use Terraform |
| Secure the endpoint / Empty the buffer / Silent the log | adjective used as verb | Make the endpoint secure / Make the buffer empty / Make the log silent |
| Static the variable / Ready the worker / Live the connection | adjective used as verb | Make the variable static / Make the worker ready / Make the connection live |
| Utilize / Leverage / Employ the service | inflated verb | Use the service |
| Commence the build / Initiate the transfer / Terminate the process | inflated verb | Start the build / Start the transfer / Stop the process |
| Orchestrate the services / Facilitate the sync | unapproved verb | Control the services / Help the sync |

Examples:

> **Non-STE:** Docker the app and deploy to production. If it fails, rollback.
>
> **STE:** Use Docker to make a container for the application. Deploy the
> container to production. If the deployment fails, roll back to the previous
> version.

> **Non-STE:** Creates a user. Caches the profile. Errors on duplicate email.
>
> **STE:** Makes a new user record. Keeps the profile in the cache. Gives an
> error on a duplicate email address.

> **Non-STE:** # init the pool, then cache the results, finally error if null
>
> **STE:** # Start the connection pool. Keep the results in the cache. Give an
> error when the value is null.

> **Non-STE:** Error: Connection timeout. The server timed out after 30s.
>
> **STE:** Error: Connection did not complete. The server did not answer within
> the 30-second timeout.

Paradigm notes: "Factory the object" and "Singleton the instance" are OOP
violations (use "Make the object with a factory", "Get the singleton
instance"). "Malloc a buffer" and "Goroutine the task" are procedural
violations (use "Make a buffer with `malloc`", "Run the task in a goroutine").
"Terraform the VPC" is a declarative violation (use "Use Terraform to make the
VPC"). In Rust, mark keywords with backticks: "The function uses `unsafe` for
the pointer access."

---

## Rule 1.3 — Use approved words only with their approved meanings

Each approved word has one specified meaning, which is often narrower than the
standard English meaning. Do not use an approved word with any other meaning.

- The approved meaning of the verb **follow** is "come after, go after". Use it
  only for sequence: "Do the steps that follow."
- The approved meaning of the verb **obey** is "to do that which the procedures
  or instructions tell you". Use it for compliance: "Obey the instructions."

Four-step check for every approved word you write:

1. **Identify the part of speech** as you used it in the sentence.
2. **Look up the approved meaning** for that part of speech in the controlled
   terminology.
3. **Ask: does my sentence use exactly that meaning?** If not, the word fails —
   even when the word is approved and the sentence reads well.
4. **Replace or restructure** so the approved word carries its approved meaning.

Worked check:

> **Sentence:** The background worker runs every night.
> **Step 1:** "runs" is a verb.
> **Step 2:** Approved meaning of "run" = "execute a program or command".
> **Step 3:** The writer means "operates on a schedule". The meaning does not match.
> **Step 4:** Rewrite: "The background worker operates every night."

Examples:

> **Non-STE:** Follow the configuration steps to set up the server. After you
> follow the steps, the service starts and listens on port 8080.
>
> **STE:** Obey the configuration instructions to set up the server. After you
> do the steps that follow, the service starts and listens on port 8080.

---

## Rule 1.4 — Use only the approved forms of verbs and adjectives

The controlled terminology gives each approved verb with its approved forms, and
each approved adjective in the base form with the comparative and superlative
forms where applicable.

Verb entry:

COMPILE (v), COMPILES, COMPILED, COMPILED

| Infinitive / imperative | Simple present | Simple past | Past participle (as adjective) |
|---|---|---|---|
| (To) Compile / Compile | Compile(s) | Compiled | Compiled |

Forms that are not listed are not permitted: "compilating" and "compilates" are
both incorrect.

Adjective entry:

FAST (adj) (FASTER, FASTEST) — base form *fast*, comparative *faster*,
superlative *fastest*. Adjectives that make their comparative and superlative
with "more" and "most" have no extra forms in the terminology, because "more"
and "most" are approved words.

Do not use the "-ing" form as a main verb in procedural writing unless the
controlled terminology lists it.

Examples:

> **Non-STE:** The compiler is compilating the source files every time you save
> the document.
>
> **STE:** The compiler compiles the source files each time you save the
> document.

> **Non-STE:** This algorithm is more fast than the previous one.
>
> **STE:** This algorithm is faster than the previous one.

> **Non-STE:** After installing the dependencies, you can start compiling the
> project by running the build script.
>
> **STE:** After you install the dependencies, compile the project with the
> build script.

---

## Rule 1.5 — Code-domain technical noun categories

A code-domain technical noun is a noun term for a specified concept in software
development, applicable to a subject field. The controlled terminology cannot
list them all, because each project uses different ones; keep yours in the
project glossary or terminology database.

You may use a code-domain technical noun in procedural and descriptive writing
when you can put it in one or more of these **nineteen** categories. The words
shown are examples only, not a complete list.

| # | Category | Example terms |
|---|---|---|
| 1 | Code components, modules, and libraries | class, controller, helper, hook, middleware, mixin, module, package, plugin, provider, repository, service, utility |
| 2 | Computing devices and their components | CPU, disk, GPU, keyboard, laptop, memory, monitor, mouse, printer, screen, server, smartphone, tablet, terminal |
| 3 | Development tools, environments, and support equipment | CLI, compiler, debugger, Docker, editor, IDE, Git, Jest, linter, loader, Prettier, terminal, test runner, TypeScript, webpack |
| 4 | Data structures, types, and formats | array, boolean, buffer, CSV, enum, hash map, integer, JSON, linked list, object, queue, stack, string, struct, tree, tuple, XML, YAML |
| 5 | Infrastructure, deployment, and platforms | AWS, CI/CD, container, deployment, Heroku, Kubernetes, load balancer, Node.js, pipeline, pod, production, staging, Vercel |
| 6 | Systems, subsystems, and architectural components | API gateway, authentication layer, caching layer, client, database layer, message broker, microservice, proxy, rate limiter, REST API, routing layer, server, WebSocket |
| 7 | Mathematical, algorithmic, and scientific terms | Big O notation, binary search, coefficient, complexity, exponent, hash function, iteration, logarithm, matrix, recursion, regex, sorting algorithm, time complexity, traversal |
| 8 | Interface elements and navigation | button, checkbox, dialog, dropdown, footer, header, menu, modal, navigation bar, radio button, scrollbar, sidebar, tab, text field, toggle, tooltip |
| 9 | Numbers, units of measurement, and time | byte, gigabyte (GB), hertz (Hz), hour (h), kilobyte (KB), megabyte (MB), millisecond (ms), minute, nanosecond (ns), second (s), terabyte (TB) |
| 10 | Quoted text (text you cannot change: error messages, code snippets, UI labels, log output) | `Cannot read properties of undefined`, `ENOENT: no such file or directory`, `Submit` button, `404 Not Found`, `connection refused` |
| 11 | Professional roles, teams, and organizations | administrator, backend developer, contributor, DevOps engineer, frontend developer, Google, maintainer, Microsoft, product owner, QA engineer, reviewer, scrum master, user |
| 12 | Official documents, API references, and standards | API reference, changelog, code of conduct, contributing guide, diagram, figure, Getting Started guide, HTTP specification, note, paragraph, README, release notes, RFC, section, table, warning |
| 13 | Runtime environments and operational conditions | development, environment variable, garbage collection, heap, hot reload, live reload, memory leak, production, sandbox, stack trace, staging, test, thread, timeout, virtual machine |
| 14 | Colors | black, blue, cyan, gray, green, magenta, orange, red, white, yellow |
| 15 | Defects, errors, and fault terminology | assertion failure, bug, crash, deadlock, defect, exception, hang, infinite loop, memory leak, null pointer, race condition, regression, stack overflow, timeout, type error |
| 16 | Computer science, information, and communication technology | AI, algorithm, authentication, authorization, blockchain, containerization, cryptography, database, encoding, encryption, firewall, hashing, internet, machine learning, metadata, neural network, protocol, query, sandbox, schema, token, virtualization |
| 17 | Legal and licensing terms | Apache 2.0, BSD license, compliance, copyright, GPL, license, MIT license, open source, proprietary, terms of service, third-party, trademark, warranty |
| 18 | Database and storage terminology | connection pool, cursor, foreign key, index, migration, NoSQL, ORM, PostgreSQL, primary key, query, Redis, relation, row, schema, seed, SQL, SQLite, stored procedure, table, transaction, view |
| 19 | Network and protocol terminology | DNS, endpoint, HTTP, HTTPS, IP address, localhost, middleware, packet, port, request, response, route, socket, SSH, TCP, TLS, UDP, URL, VPN, WebSocket |

Note on category 14: colors are adjectives, but STE-Code identifies them as
code-domain technical nouns. Comparative and superlative forms of colors (for
example "blacker", "the reddest") are not permitted.

---

## Rule 1.6 — Unapproved words are permitted only inside technical nouns

A word that the controlled terminology marks as not approved fails when you use
it as a general noun or adjective, and passes when it is part of a recognized
code-domain technical noun.

**"Handler"** — not approved; the alternative is "function (n)".

> **Non-STE:** The handler processes each incoming event.
>
> **STE:** The function processes each incoming event.
>
> **STE:** The event handler processes each incoming event.
> ("Event handler" is a code-domain technical noun, category 1.)

**"Main"** — not approved as a general adjective; the alternative is
"primary (adj)".

> **Non-STE:** The main configuration has the latest values.
>
> **STE:** The primary configuration has the latest values.
>
> **STE:** Merge the feature branch into the main branch.
> ("Main branch" is a code-domain technical noun, category 5. Do not write
> "primary branch" — that is not the approved technical noun.)

**"Base"** — not approved for a surface location; the alternative is
"bottom (n)". "Base" stays inside the technical nouns "base case" (category 7)
and "base class" (category 1).

> **Non-STE:** Copy the files to the base of the build folder.
>
> **STE:** Copy the files to the bottom of the build folder.

---

## Rule 1.7 — Do not use code-domain technical nouns as verbs

Use a code-domain technical noun only as a noun, or as an adjective inside a
different technical noun. Restructure the sentence with an approved verb.

> **Non-STE:** Database the user records before the migration.
>
> **STE:** Store the user records in the database before the migration.

> **Non-STE:** Cache the API responses to improve performance.
>
> **STE:** Store the API responses in the cache to improve performance.

A word can be a technical noun **and** a technical verb when it fits a category
in Rule 1.5 and a category in Rule 1.12. Your project glossary decides:

> **STE (noun):** Write a log entry for each failed request.
>
> **STE (verb):** Log each failed request.

If your glossary lists the word only as a technical noun, obey Rule 1.7 and use
a different sentence construction.

> **See also:** Rule 1.5, Rule 1.12, Rule 1.13.

---

## Rule 1.8 — Use the technical nouns approved in your project or field

If your project, company, industry, or subject field already has an approved
name for a class, module, function, method, variable, component, or process,
use that name. These names live in your project glossary, API documentation,
coding standards, or company documentation.

Do not invent your own names for items that already have established names.
The source of truth is the repository.

> **STE:** The dashboard page has a `UserTable` component and a `FilterPanel`
> component.

> **Non-STE:** The account controller manages login and user profile operations.
>
> **STE:** The `AccountController` manages authentication and user profile
> operations.

---

## Rule 1.9 — Select short, easy technical nouns

When no approved technical noun exists in your project, company, industry, or
subject field, select one that is short (not more than three words) and easy to
understand. Do not write a long descriptive phrase when a shorter term is
enough. When the context identifies the item — a code snippet, a line number, a
diagram, an API reference — use the shortest unambiguous term. Add one or two
adjectives only when clarification is necessary.

```javascript
// client.js — line 42
async function fetchUtility(url) {
  const response = await fetch(url);
  return response.json();
}
```

> **Non-STE:** Call the asynchronous JavaScript XML HTTP request wrapper utility
> function (line 42) to get the serialized JSON payload from the remote
> application programming interface endpoint.
>
> **STE:** Call the `fetchUtility` function (line 42) to get the JSON data from
> the API endpoint.

---

## Rule 1.10 — No regional, slang, or jargon words as technical nouns

Some technical words are used only inside confined communities or single
technology ecosystems. They are not easy to understand for readers from a
different background or stack. Code documentation is read by junior developers,
developers from other language communities, and non-native English speakers: a
word that one subculture finds clear can be opaque to every other reader.
Always select well-known words.

| Do not write | Write |
|---|---|
| Remove all the cruft from the legacy module. | Remove all the unnecessary code from the legacy module. |
| The function monkeys with the input data before validation. | The function changes the input data before validation. |
| Bikeshedding delayed the API design by two weeks. | Unnecessary discussion about small details delayed the API design by two weeks. |
| I spent the morning yak shaving before I could write the test. | I spent the morning completing unrelated prerequisite tasks before I could write the test. |
| Replace the foo and bar placeholders with real values. | Replace the example and placeholder values with real values. |

---

## Rule 1.11 — One technical noun per item

Do not use a different code-domain technical noun in another part of your
documentation for the same item. Changing the name of one item between sections
forces the reader to decide whether you mean the same item or a different one.
The source of truth for the name is the code: the class, function, module,
table, resource, environment variable, or configuration key as it is defined in
the repository.

> **Non-STE:**
> 1. Initialize the UserService class to start the session manager.
> 2. Call the authenticate method on the AccountManager to verify a user.
> 3. The UserHandler returns a session token that you send in later requests.
>
> **STE:**
> 1. Initialize the UserService class to start the session manager.
> 2. Call the authenticate method on the UserService to verify a user.
> 3. The UserService returns a session token that you send in later requests.

> **Non-STE:** "/api/login path", "authentication route", "login endpoint" —
> three names for one endpoint.
>
> **STE:** Use "/api/login endpoint" in every sentence, because the OpenAPI file
> defines the path as `/api/login`.

---

<!-- 02-synonyms.md -->

# Level 3 — Synonyms and Approved Words

This slice defines how to choose words in STE-Code when the approved-words
dictionary does not contain the term you need. It covers the **technical-noun
category system** (Rule 1.5) and the rules that govern unapproved-word use and
synonym selection (Rules 1.6–1.11).

Core idea: the dictionary lists approved everyday words. When you need a
word not in the dictionary, you may still use it if it qualifies as a
**technical noun** — a noun term for a specified software concept that fits one
of 19 categories. This lets project-specific terminology (class names, protocol
names, metrics, error strings) appear in documentation without breaking
controlled-language rules.

## Rule 1.5 — Technical noun categories (framework)

You can use a term in code documentation if you can include it in a technical
noun category.

- A **technical noun** is a noun term that refers to a specified software
  concept and is applicable to a given codebase, library, or system.
- The approved-words dictionary does not list project-specific technical nouns
  because each codebase, framework, and ecosystem uses different terminology.
- Find these terms in your project glossary, API reference, or architecture
  decision records (ADRs).
- Use technical nouns in procedural and descriptive documentation — API
  references, commit messages, READMEs, code comments, technical specs — when
  they fit one or more of the 19 categories below.

Non-STE vs STE:

| Non-STE | STE |
|---------|-----|
| Use the thing to call the function that gets data from the database. | Use the `fetchUser` method of the `UserRepository` to retrieve a `User` record from the `PostgreSQL` database. |
| ("thing", "gets data" — no technical nouns; ambiguous) | (`fetchUser`, `UserRepository`, `User`, `PostgreSQL` — all classified technical nouns) |

## The 19 technical noun categories

Each category below lists **code-domain** terms that count as technical nouns.
A term fits if it refers to a specified software concept of that kind. The lists
are examples, not a closed vocabulary — add project-specific terms via your
glossary.

### 1. API and library components
Terms for API and library components: endpoint, method, parameter, query
parameter, path parameter, request body, response body, header, status code,
module, class, interface, type alias, enum, constant, decorator, middleware,
route handler, serializer, DTO, model, schema, callback, hook, plugin.
- STE: Call the `POST /api/v1/users` endpoint with a `CreateUserRequest` body
  to create a `User` resource.

### 2. Applications, services, and subsystems
Web application, mobile app, desktop client, CLI tool, microservice, monolith,
API gateway, load balancer, database server, message broker, cache layer,
container, pod, cluster, frontend, backend, admin panel, user dashboard,
authentication service, payment service, notification service, search engine,
CDN, reverse proxy, serverless function, cron job, worker process.
- STE: The `nginx` reverse proxy on the `web-01` frontend server stopped
  responding.

### 3. Development tools and SDKs
IDE, code editor, terminal emulator, compiler, interpreter, transpiler, bundler,
linter, formatter, debugger, profiler, package manager, version control system,
CI runner, test framework, assertion library, mocking library, static analyzer,
API client, database client, container runtime, orchestration tool, IaC tool,
monitoring dashboard, log aggregator, feature flag service, secrets manager.
- STE: Run `ESLint` with the `@company/eslint-config` preset to find lint
  violations.

### 4. Dependencies, packages, technical debt
Dependency, transitive dependency, package, library, framework, runtime,
polyfill, shim, vendor bundle, dead code, deprecated API, legacy module,
orphaned code, code smell, TODO comment, FIXME comment, zombie import, circular
dependency, peer dependency, dev dependency, optional dependency, pinned
version, lockfile, SBOM, supply chain artifact, third-party script, ad-hoc
patch, monkey-patch, workaround code.
- STE: Remove the deprecated `UserService.legacyCreate()` method — dead code
  with zero callers as of v3.2.

### 5. Hosting, CI/CD, deployment infrastructure
Cloud provider, region, availability zone, data center, Kubernetes cluster,
namespace, Docker registry, artifact repository, build pipeline, deployment
pipeline, staging environment, production environment, sandbox environment,
on-premise server, virtual machine, bare-metal host, edge location, CDN
endpoint, storage bucket, message queue, event bus, API gateway endpoint, load
balancer target group, auto-scaling group, service mesh, ingress controller.
- STE: Deploy the `orders-service` container image to the `us-east-1`
  `production` Kubernetes cluster in namespace `orders`.

### 6. Software system design and architecture
Architecture, design pattern, layered architecture, hexagonal architecture,
microservice, event-driven architecture, CQRS, event sourcing, pub/sub, message
queue, event bus, database shard, read replica, write-ahead log, connection
pool, circuit breaker, retry policy, rate limiter, cache layer, CDN edge,
feature flag, A/B test variant, canary deployment, blue-green deployment,
rolling update, service registry, configuration provider, secret store, reverse
proxy, API gateway route, middleware chain, plugin system, dependency injection
container, ORM, migration runner.
- STE: The `PaymentGateway` client uses a `CircuitBreaker` pattern — after 5
  consecutive failures it opens and returns cached fallback responses for 30 s.

### 7. Algorithms, data structures, computational concepts
Algorithm, data structure, Big-O notation, time complexity, space complexity,
hash table, binary tree, linked list, graph, trie, bloom filter, LRU cache,
consistent hashing, recursion, memoization, dynamic programming, greedy
algorithm, backtracking, binary search, quicksort, mergesort, topological sort,
Dijkstra, BFS, DFS, A*, Paxos, Raft, two-phase commit, saga pattern, idempotency
key, eventual consistency, CAP theorem, ACID, BASE, vector clock, Lamport
timestamp, Merkle tree, shard key, partition key, compound index, covering
index, query plan, cardinality, selectivity, normalization, denormalization,
OLTP, OLAP, ETL, stream processing, batch processing, map-reduce, actor model,
CSP, semaphore, mutex, atomic operation, CAS.
- STE: `computeShippingCost(addressHash)` is memoized with an `LRU Cache`
  (capacity 1024, `O(1)` eviction) to avoid redundant API calls.

### 8. Codebase navigation and project structure
Directory, subdirectory, file path, import path, package root, module root,
workspace root, monorepo root, source directory, test directory, build output,
entry point, barrel export, index file, re-export, absolute import, relative
import, path alias, symlink, Git root, branch, tag, commit, HEAD, upstream,
origin, fork, submodule, subtree, vendor directory, node_modules, virtual
environment, GOPATH, classpath, namespace, package scope, module scope, public
API surface, internal package, private module, exported symbol.
- STE: The `formatCurrency` helper is in `src/shared/utils/formatting.ts`,
  re-exported from the barrel file at `src/shared/utils/index.ts`.

### 9. Metrics, timing, quantitative measurements
Latency, throughput, response time, p50, p95, p99, p999, ops/sec, req/sec, RPM,
RPS, QPS, TPS, bytes, KB, MB, GB, TB, KiB, MiB, ms, µs, ns, s, min, hr, CPU
core, thread count, memory usage, heap size, stack size, GC pause, cold start
time, warm start time, bootstrap time, build time, deploy time, MTTR, MTBF,
uptime, downtime, error rate, success rate, availability (99.9%, 99.99%), RPO,
RTO, SLO, SLI, SLA, concurrency, connection count, pool size, batch size, page
size, offset, limit, TTL, timeout, interval, poll interval, retry delay, backoff
multiplier, rate limit (tokens/sec), quota, sample rate, cardinality.
- STE: The `GET /search` endpoint has a p95 latency of 120 ms and a p99 latency
  of 350 ms at 5000 RPM.

### 10. Quoted text (cannot change)
Quoted error messages, log output, API responses, UI string literals, CLI
output: error message, stack trace, log line, HTTP response body, JSON payload,
XML response, environment variable value, CLI flag, command option, shell
command output, status code text, exception message, assertion message,
deprecation warning, compiler diagnostic, linter rule ID, test failure message,
benchmark output, profiler report, API route pattern, SQL query string, GraphQL
query, regex pattern, glob pattern, cron expression, semantic version string,
git commit hash, UUID string, JWT token (example), `"Connection refused"`,
`"404 Not Found"`, `"TypeError: Cannot read properties of undefined"`,
`"--config=./prod.yaml"`, `"npm ERR! code ERESOLVE"`.
- STE: If the application logs `"FATAL: sorry, too many clients already"` from
  `PostgreSQL`, restart the `pgbouncer` connection pooler.

### 11. Project roles, teams, organizations, entities
Maintainer, author, contributor, reviewer, approver, code owner, release
manager, on-call engineer, SRE, DevOps engineer, security champion, triage team,
core team, steering committee, technical lead, staff engineer, principal
engineer, intern, vendor, client, stakeholder, end user, GitHub organization,
npm organization, Docker Hub organization, CNCF, Apache Software Foundation,
Linux Foundation, Mozilla, Google, Microsoft, OpenAPI Initiative, ECMA, ISO,
W3C, IETF, OWASP, `CODEOWNERS` file, `@backend-team`, `@security-reviewers`.
- STE: Request a review from `@frontend-core` (code owners for `src/components/`
  per `.github/CODEOWNERS`).

### 12. UI elements, interaction points, accessibility
Button, text input, checkbox, radio button, dropdown, select menu, toggle,
slider, modal, dialog, tooltip, popover, toast, snackbar, banner, tab, accordion,
breadcrumb, pagination, carousel, card, table, data grid, form, form field,
label, placeholder, icon, avatar, badge, spinner, progress bar, skeleton loader,
navbar, sidebar, footer, header, search bar, filter panel, drawer, split pane,
context menu, keyboard shortcut, hotkey, focus trap, skip link, screen reader
label, ARIA role, ARIA attribute, landmark region, heading hierarchy.
- STE: Click the `hamburger` icon in the `Navbar` to open the `Sidebar` drawer
  (ARIA role `navigation`, label "Main menu").

### 13. User data, preferences, session state
User profile, display name, avatar URL, email address, phone number, billing
address, shipping address, payment method, credit card, subscription plan, usage
quota, rate limit bucket, API key, access token, refresh token, ID token,
session cookie, CSRF token, user preference, theme setting, language locale,
timezone, notification setting, opt-in flag, consent record, bookmark,
watchlist, shopping cart, wishlist, search history, recently viewed, draft
content, clipboard data, localStorage key, IndexedDB store, browser fingerprint,
device ID, push notification token.
- STE: Persist the user's `uiPreferences` (theme `"dark"`, locale `"en-GB"`,
  timezone `"Europe/London"`) to `localStorage` under key `user_prefs_v2`.

### 14. System health, diagnostics, observability, failure modes
Health check, liveness probe, readiness probe, startup probe, heartbeat, ping,
metric, trace, span, log level, structured log, correlation ID, trace ID, span
ID, alert, incident, SLO, SLI, error budget, burn rate, on-call rotation,
escalation policy, runbook, playbook, postmortem, root cause analysis (RCA),
mean time to recovery (MTTR), mean time to detection (MTTD), anomaly detection,
threshold breach, saturation, latency tail, error spike, traffic drop, resource
exhaustion, memory pressure, disk pressure, CPU throttling, GC thrashing,
connection storm, thundering herd, cascading failure, split-brain, partition,
degraded state, brownout, blackout.
- STE: The `payments-service` `readinessProbe` is failing — `/healthz` returns
  HTTP 503; the service is `degraded` and removed from the load balancer target
  group.

### 15. Documents, standards, specifications, their parts
README, CHANGELOG, CONTRIBUTING, LICENSE, CODE_OF_CONDUCT, SECURITY, GOVERNANCE,
ARCHITECTURE, ADR (Architecture Decision Record), RFC (Request for Comments),
API reference, OpenAPI spec, GraphQL schema, AsyncAPI spec, style guide, coding
standard, linting rules, PR template, issue template, discussion template,
release notes, migration guide, upgrade guide, getting started guide, quickstart,
tutorial, how-to guide, explanation, reference, concept document, FAQ, glossary,
onboarding guide, runbook, playbook, incident report, postmortem, design doc,
technical spec, product requirements document (PRD), test plan, test case,
acceptance criteria, Definition of Done, Definition of Ready, service level
agreement (SLA), terms of service (TOS), privacy policy, cookie policy, data
processing agreement (DPA), semantic versioning (SemVer), conventional commits,
Git commit message format, doc comment, TSDoc, JSDoc, godoc, docstring,
annotation, attribute, decorator doc, heading, subheading, section, subsection,
paragraph, code block, table, list, admonition (note, warning, tip, danger,
caution, important), hyperlink, cross-reference, footnote, bibliography, index,
glossary entry, TOC (table of contents).
- STE: Record the decision in an ADR
  (`docs/adr/0014-use-event-sourcing-for-orders.md`) with Context, Decision,
  Consequences, Alternatives Considered sections.

### 16. Runtime environments, execution contexts, operating parameters
Production, staging, development, testing, CI, localhost, operating system, OS
version, kernel version, distribution, CPU architecture (x86_64, arm64), Node.js
version, Python version, Java version, Go version, browser, browser version,
rendering engine, screen resolution, viewport size, device type, network
condition (offline, slow 3G, 4G, WiFi), Docker image, container runtime,
Kubernetes version, cloud region, availability zone, environment variable, build
flag, feature flag state, A/B test bucket, configuration profile, Spring
profile, Rails environment, NODE_ENV, DEBUG mode, verbose logging, trace level,
read-only mode, maintenance mode, degraded mode, dark mode, high contrast mode,
reduced motion, forced colors, RTL locale, daylight saving time transition, leap
second, timezone offset.
- STE: The `TextRenderer` crash only reproduces on `macOS 14.5` (arm64) with
  `Node.js 20.11.0` — the `canvas` native addon fails to load the prebuilt
  binary.

### 17. Colors and theme tokens
Primary, secondary, accent, success, warning, error, info, neutral, background,
surface, text, border, divider, shadow, overlay, red, green, blue, yellow,
orange, purple, pink, teal, cyan, gray, black, white, transparent, hex code
(`#FF5733`, `#1A1A2E`), RGB (`rgb(255, 87, 51)`), RGBA (`rgba(26, 26, 46, 0.8)`),
HSL (`hsl(12, 100%, 60%)`), CSS custom property (`--color-primary-500`,
`--color-text-on-primary`), design token, color ramp, color scale (50-900), light
mode, dark mode, high contrast mode, color blindness safe palette, WCAG contrast
ratio, semantic color, Brand Color.
- Colors in design systems are technical nouns. Do NOT use comparative forms
  ("darker", "lightest") — reference the specific design token or ramp step.
- STE: Set the page background to `--color-surface-page` (resolves to `#FFFFFF`
  in light mode, `#121212` in dark mode), WCAG AA contrast ≥ 4.5:1.

### 18. Bugs, errors, exceptions, failure modes
Crash, segfault, null pointer exception, undefined is not a function, type error,
reference error, syntax error, range error, stack overflow, buffer overflow,
memory leak, resource leak, dangling pointer, use-after-free, double free, race
condition, deadlock, livelock, starvation, priority inversion, ABA problem, torn
read, torn write, dirty read, non-repeatable read, phantom read, lost update,
write skew, serialization anomaly, split-brain, network partition, timeout,
connection reset, DNS failure, TLS handshake failure, certificate expiry,
HTTP 500, HTTP 502, HTTP 503, HTTP 504, rate limit exceeded, quota exceeded, out
of memory (OOM), disk full, inode exhaustion, file descriptor exhaustion, thread
pool exhaustion, connection pool exhaustion, GC thrashing, cache stampede, cache
penetration, cache avalanche, hot partition, data corruption, bit rot, checksum
failure, hash collision, infinite loop, infinite recursion, integer overflow,
integer underflow, floating point precision error, off-by-one error, SQL
injection, XSS, CSRF, prototype pollution, deserialization vulnerability,
dependency confusion, supply chain attack, CVE, CWE, zero-day.
- STE: `OrderProcessor` has a race condition: threads A and B both check
  `inventory[sku].quantity > 0` before either decrements — oversell. Fix:
  `SELECT ... FOR UPDATE` row lock.

### 19. Computer science and ICT
API, REST, GraphQL, gRPC, WebSocket, SSE, HTTP/2, HTTP/3, TCP, UDP, TLS, mTLS,
OAuth 2.0, OIDC, SAML, JWT, API key, CORS, CSP, HSTS, DNS, CDN, IP, IPv4, IPv6,
CIDR, VPN, VPC, subnet, firewall rule, WAF, DDoS, load balancing, reverse proxy,
forward proxy, caching, compression, serialization (JSON, Protobuf, MessagePack,
Avro), encoding (Base64, URL encoding), hashing (SHA-256, bcrypt, Argon2),
encryption (AES-256-GCM, RSA, ECDSA), encoding (UTF-8, ASCII), Unicode, emoji,
regex, glob pattern, SQL, NoSQL, ORM, migration, seed data, transaction, ACID,
BASE, sharding, replication, partitioning, indexing, normalization,
denormalization, message queue, pub/sub, event sourcing, CQRS, saga, distributed
transaction, consensus, leader election, service discovery, circuit breaker,
bulkhead, retry, backoff, idempotency, rate limiting, throttling, API versioning,
semantic versioning, feature flag, canary release, blue-green deployment, rolling
update, immutable infrastructure, infrastructure as code, configuration as code,
GitOps, observability, telemetry, tracing, metrics, logging, profiling, APM, RUM,
continuous integration, continuous delivery, continuous deployment, DevOps,
DevSecOps, Git, Docker, Kubernetes, Helm, Terraform, Ansible.
- STE: `Orders API` uses OAuth 2.0 Authorization Code flow (PKCE); clients get a
  JWT from `POST /oauth/token` and pass it in the `Authorization: Bearer <token>` header.

### 20. DevOps, release management, lifecycle support
Deployment, release, rollout, rollback, hotfix, patch, minor release, major
release, breaking change, deprecation, end-of-life (EOL), sunset, migration,
upgrade path, backward compatibility, forward compatibility, downtime,
maintenance window, zero-downtime deployment, graceful shutdown, drain, scale up,
scale down, scale out, scale in, autoscaling, horizontal scaling, vertical
scaling, incident, outage, service disruption, failover, disaster recovery,
backup, restore, point-in-time recovery, snapshot, retention policy, runbook
execution, playbook, on-call handoff, escalation, war room, status page, SLA
breach, SLO violation, error budget policy, change freeze, code freeze, release
train, sprint, iteration, milestone, roadmap, epic, user story, bug ticket,
triage, priority (P0, P1, P2, P3), severity (SEV0, SEV1, SEV2, SEV3), SL1-SL4,
service level objective, operational level agreement (OLA), underpinning
contract (UC), vendor management, procurement, onboarding, offboarding, access
revocation, audit log, compliance check, penetration test, vulnerability scan,
security patch, responsible disclosure, coordinated vulnerability disclosure
(CVD).
- STE: Initiate a hotfix: cherry-pick `fix/payment-null-pointer` onto
  `release/v3.2`, trigger `deploy-hotfix`, canary at 10% for 30 min before full
  rollout.

### 21. Licenses, compliance, regulatory and legal texts
License, open-source license, proprietary license, MIT License, Apache 2.0
License, GPLv3, LGPL, BSD, AGPL, MPL, Unlicense, Creative Commons, EULA, terms of
service (TOS), privacy policy, cookie policy, data processing agreement (DPA),
service level agreement (SLA), contributor license agreement (CLA), Developer
Certificate of Origin (DCO), copyright, trademark, patent, intellectual property,
attribution, copyleft, permissive license, compliance, regulatory compliance,
GDPR, CCPA, HIPAA, SOC 2, ISO 27001, PCI DSS, FedRAMP, FISMA, export control, EAR,
ITAR, sanctions list, embargo, data residency, data sovereignty, data retention
policy, right to erasure, right to access, data subject request (DSR), personal
data, PII, PHI, sensitive data, data classification, data handling policy,
acceptable use policy, code of conduct, vendor risk assessment, security
questionnaire (CAIQ, SIG), audit report, attestation, SOC report, penetration
test report, vulnerability disclosure policy, bug bounty program terms,
responsible disclosure policy, indemnification, limitation of liability, warranty
disclaimer, governing law, jurisdiction, severability, force majeure, assignment,
termination, survival clause, third-party notice, open-source attribution,
NOTICE file, SBOM.
- STE: The `request@2.88.2` package has a missing license field — replace with
  `node-fetch@3.3.2` (MIT). Validate with `npx license-checker --onlyAllow
  "MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause"`.

### 22. Test fixtures, mock data, sample datasets, placeholders
Test fixture, mock object, stub, spy, fake, dummy, test double, seed data, sample
data, example record, placeholder, synthetic data, faker data, lorem ipsum,
"John Doe", "Jane Smith", "Acme Corp", "example.com", "test@example.com",
"user_12345", "order_abc", "00000000-0000-0000-0000-000000000000", "foo", "bar",
"baz", "qux", "quux", "spam", "eggs", "ham", "hello world", "TODO", "FIXME",
"HACK", "XXX", "WIP", "tmp", "scratch", "sandbox", "playground", "hello-world-app",
"my-first-repo", "boilerplate", "starter-kit", "todo-mvc", "hello-kubernetes",
"nginx-hello", "FakeUser", "MockOrderRepository", "StubPaymentGateway",
"InMemoryDatabase", "NullLogger", "noop", `TestUserFactory.create()`,
`Fixtures.defaultUser()`, `faker.internet.email()`.
- STE: The `OrderService` test uses `Fixtures.defaultOrder()` and a
  `MockPaymentGateway` stub that returns `PaymentResult.SUCCESS` without real
  HTTP calls.

## Related rules — unapproved words, synonyms, technical-noun use

### Rule 1.6 — Use an unapproved word only as a technical noun
Use a word that is not approved in the standard documentation vocabulary only
when it is a technical noun (classified in one of the 19 categories) or part of a
technical noun.

| Non-STE | STE |
|---------|-----|
| The `base` class holds shared logic for all the page objects. | The `BasePage` class (technical noun, Category 1: API and library components) holds shared logic for all `PageObject` subclasses. |
| ("base" is ambiguous — common word or class name?) | (`BasePage` is a classified technical noun — intentional, project-specific identifier.) |

### Rule 1.7 — Do not verb technical nouns
Do not use words that are technical nouns as verbs in code documentation.

| Non-STE | STE |
|---------|-----|
| `docker` the container and `curl` the endpoint to verify it. | Build the `Docker` image (Category 5: Hosting, CI/CD) and send a request to the endpoint using `curl` (Category 3: Development tools). |

### Rule 1.8 — Use approved technical nouns
Use technical nouns that are approved in your project glossary, organization
style guide, or ecosystem conventions.

| Non-STE | STE |
|---------|-----|
| The `data fetcher thing` in the `store layer` gets records from the `DB`. | The `Repository` pattern implementation (`UserRepository`) in the `data` layer fetches `User` entities from `PostgreSQL` via `TypeORM`. |

### Rule 1.9 — Keep technical nouns short
When you must select a technical noun for code documentation, use one which is
short (not more than three words) and easy to understand.

| Non-STE | STE |
|---------|-----|
| Call the `asynchronous JavaScript Object Notation web token-based user authentication and authorization pre-validation middleware handler`. | Call the `JWT auth middleware`. |

### Rule 1.10 — No slang, regional, or jargon technical nouns
Do not use team-internal slang, regional programming jargon, or company-specific
nicknames as technical nouns in public-facing documentation.

| Non-STE | STE |
|---------|-----|
| The `magic button` on the `admin doodad page` sends a `zap` to the `thingamajig service`. | The `"Sync All"` button on the `Admin Dashboard` sends a `POST` request to the `DataSyncService`. |

### Rule 1.11 — One technical noun per entity
Do not use different technical nouns for the same software entity across your
documentation.

| Non-STE | STE |
|---------|-----|
| Step 1: Call the `UserFetcher` service. Step 2: Configure the `AccountRetriever` module. Step 3: Restart the `ProfileLoader` microservice. | Step 1: Call the `UserService`. Step 2: Configure the `UserService`. Step 3: Restart the `UserService` microservice. |

## Closing notes

- The terms listed in each category are **examples only**. Rule 1.5 does not
  give a full list of all possible technical nouns for code documentation.
- Listed terms use backtick formatting (`LikeThis`) only when the term is a
  literal identifier, API name, or exact string value from code — for example,
  class names, function names, environment variable names, and error message
  strings.
- Add project-specific technical nouns to your project glossary or terminology
  database; they then qualify as approved technical nouns under these categories.

## Quick reference for LLM code-doc generation

1. If the word is in the approved-words dictionary, use it as written.
2. If the word is not in the dictionary, check whether it fits a technical-noun
   category (1–22). If yes, you may use it — preferably verbatim as an
   identifier (`ClassName`) when it is a literal code name.
3. Never verb a technical noun (Rule 1.7); never use slang nicknames for
   public docs (Rule 1.10); never invent multiple names for one entity
   (Rule 1.11).
4. Keep added technical nouns short (≤ 3 words) and consistent with the project
   glossary (Rules 1.9, 1.8, 1.11).

---

<!-- 03-dictionary.md -->

## Dictionary excerpt (approved / unapproved)

# STE-Code Adapted Dictionary A-Z

> **Source:** Adapted from ASD-STE100 Issue 9, Part 2 - Dictionary, Pages 149-434
> **Source file:** ste-code/merged/master.md (lines 5591-10976)
> **Generated:** 2026-07-30
> **Domain adaptation:** aerospace → code documentation (API docs, commit messages, README sections, code comments)
> **Preserved:** word alphabetization, STE/non-STE pair format, approved/unapproved status, parts of speech
> **Replaced:** aerospace examples with code examples
> **Approved words:** ~875 (UPPERCASE) | **Unapproved words:** ~1274 (lowercase + UNNAPROVED)

---

## How to Read This Dictionary

- **UPPERCASE words** are approved in STE-Code.
- **lowercase words** are not approved; use the listed alternatives instead.
- **(v)** = verb, **(n)** = noun, **(adj)** = adjective, **(adv)** = adverb, **(prep)** = preposition, **(conj)** = conjunction, **(pron)** = pronoun, **(art)** = article
- **(TN)** = code-domain Technical Noun, **(TV)** = code-domain Technical Verb
- Each entry shows: original rule text → code-domain rewrite → STE/non-STE code example pairs

---

# A

## A (art)
- **Original:** Function word: indefinite article. A FUEL PUMP IS INSTALLED IN ZONE 10.
- **Code-domain:** Function word: indefinite article. A CONFIG FILE IS INCLUDED IN THE ROOT DIRECTORY.
> **STE:** A config file is included in the root directory.
> **Non-STE:** Config files included in root directory.

*Ref: master.md - Dictionary entry A (art), Page 149*

---

## ABANDON (v) - UNNAPROVED
- **Original:** GO (v), STOP (v). IF THERE IS A FIRE, IMMEDIATELY GO TO A SAFE AREA. / IF THE VALUES ARE INCORRECT, STOP THE TEST PROCEDURE.
- **Code-domain:** TERMINATE (v), STOP (v). IF THE BUILD FAILS, STOP THE DEPLOYMENT PIPELINE. / IF THE VALUES ARE INCORRECT, TERMINATE THE TEST RUN.
> **STE:** If the build fails, stop the deployment pipeline.
> **Non-STE:** If the build fails, abandon the deployment pipeline.

> **STE:** If the values are incorrect, terminate the test run.
> **Non-STE:** If the values are incorrect, abandon the test procedure.

*Ref: master.md - Dictionary entry abandon (v), Page 149*

---

## ABILITY (n) - UNNAPROVED
- **Original:** CAN (v). ONE GENERATOR CAN SUPPLY POWER FOR ALL THE SYSTEMS.
- **Code-domain:** CAN (v). ONE CONFIGURATION CAN HANDLE REQUESTS FOR ALL THE ENDPOINTS.
> **STE:** One configuration can handle requests for all the endpoints.
> **Non-STE:** One configuration has the ability to handle requests for all the endpoints.

*Ref: master.md

---

<!-- 04-templates.md -->

# Level 3 — Document Templates (All Code-Documentation Types)

This slice gives ready-to-fill templates for the document types where STE-Code
matters most in daily engineering work, and the rules that govern how a sentence
in any of them is built. It pairs with `01-principles.md` (words) and
`03-dictionary.md` (terminology).

Level 1 gave the word-level gate (Rules 1.1–1.14). Level 2 applied it to review
and pull-request text. Level 3 widens the lens to **every** code-documentation
type and states the governing sentence-level rules directly so an LLM can apply
them without cross-referencing the full standard.

Every template below follows the same three constraints:

1. **Word gate** — each word you add passes one of: approved in the controlled
   terminology (the STE-Code dictionary), a code-domain technical noun (Rule 1.5,
   19 categories), or a code-domain technical verb (Rule 1.12).
2. **Imperative action** — every instruction line starts with a base verb, no
   "must", no modal verb, no passive voice (Rule 5.3).
3. **One technical noun per item** — name the same symbol the same way every
   time, in backticks, uninflected (Rules 1.5, 1.11).

---

## Governing rules

These four sentence-level rules apply to every template in this slice. Read them
once; apply them everywhere.

### Rule 5.3 — Imperative (command) form for instructions

Write every instruction in the imperative (command) form: start with a base verb,
omit the subject "you" (implied), and give a direct instruction.

- Do **not** use passive voice ("The tests are run by CI"), gerunds
  ("Running the tests…"), or modal verbs ("can", "could", "should", "may",
  "might", "would").
- Do **not** put "must" before the imperative in a standard instruction. Reserve
  "must" for WARNING / CAUTION blocks (security, data loss, safety). Example:
  "WARNING: IF YOU MUST DELETE THE DATABASE, FIRST MAKE A BACKUP."
- Use the base verb for the action: "Set the port to 8080", not "The port should
  be set to 8080".

Document-type boundaries:

- **README** — use the imperative only for procedural sections (install,
  configure, build, quick-start). Descriptive sections (project goals, feature
  lists, architecture summary) may use declarative sentences.
- **API docs** — endpoint descriptions are descriptive ("Returns a list of
  users"); the imperative applies to setup, auth walkthroughs, and "getting
  started" steps. Example request blocks are inherently imperative.
- **Docstrings / inline comments** — describe behavior, don't command the
  reader ("This function returns the profile for the user ID", not "Return the
  profile"). Exception: shell-script headers and Makefile target comments, which
  the reader executes.
- **Commit messages** — the subject line is imperative and completes "If
  applied, this commit will…": "Fix the race condition", not "Fixed the race
  condition". The body may use descriptive sentences.
- **Error messages** — describe what failed, then give a recovery instruction,
  separated by a period or newline: "The port 8080 is already in use. Set a
  different port with the `--port` option."

> **Non-STE:** The test suite can be executed with `npm test`.
> **STE:** Run the unit tests with `npm test`.

> **Non-STE:** Before you delete the branch, you must push all local commits.
> **STE:** Before you delete the branch, push all local commits to the remote.

### Rule 5.4 — Descriptive statement before the command

When the reader must know a condition before they act, write it as a descriptive
statement, then a **comma**, then the imperative command. The comma is required:
its position determines which verb an adverb modifies.

> **STE:** If the connection pool is full, reject the request.
> (comma after "full" → "reject" is the command)
> **STE:** If the connection pool is full automatically, reject the request.
> (comma after "automatically" → the pool fills on its own)

- Keep one condition per sentence. For multi-step procedures, write each
  condition–command pair as a separate step.
- Apply inside every template that has a "condition then action" shape (T2
  `Result` → `Required change`, T4 `Scope` sets the condition, T5 `How` steps).

> **Non-STE:** Run the database migration after you set `DATABASE_URL` and
> confirmed the server accepts connections.
> **STE:** After you set the `DATABASE_URL` variable, run the database migration.

### Rule 3.6 — Active voice

Use the active voice in all code documentation. The subject does the action.
Passive voice is permitted in descriptive writing **only** when the agent (the
person, service, or component that does the action) is unknown.

Test: ask "by whom or by what?" If the sentence answers that question, it is
passive — convert by making the agent the subject.

- **Passive:** The circuits are connected by a switching relay.
- **Active:** A switching relay connects the circuits.
- **Passive (agent unknown, allowed):** During transmission, the data was
  corrupted.

### Rule 9.4 — Consistent style

When you select terminology or wording, use the same style every time the same
type of step occurs. Three dimensions, each audited independently:

- **Lexical** — one term per concept ("config file", never "settings file" /
  "config" / "config file" alternating).
- **Syntactic** — same grammatical template for the same action type ("Install
  the package to add the CLI tool"; don't switch some steps to passive or
  conditional).
- **Semantic** — a term keeps the same meaning across every file, module, and
  doc type ("build" means the same thing in the README as in the CI docs).

Apply per doc type:

- **README** — one word for the project artifact ("library", not "package" in
  paragraph 3).
- **API docs** — an endpoint/parameter has exactly one name across all
  references; map prose to the schema by name.
- **Docstrings** — use the same term as the function signature (parameter
  `max_retries`, not "maximum attempts").
- **Commit messages** — same imperative verb for the same category of change
  across the project ("Add", never "Introduce"/"Insert"/"Create" mixed in).
- **Error messages** — one error code produces the same text every time;
  operators search logs by message.
- **CLI / help text** — a flag's description matches in `--help`, man pages,
  docs, and error messages.

```markdown
## Non-STE (inconsistent)
1. Open the configuration file in a text editor.
2. Change the port number in the settings file.
3. Save the config and close it.
4. Compile the project with the build command.
5. Make the binary for the target platform.

## STE (consistent)
1. Open the configuration file in a text editor.
2. Change the port number in the configuration file.
3. Save the configuration file and close it.
4. Build the project with the build command.
5. Build the binary for the target platform.
```

### Rule 1.5 grammar — technical nouns in running text

Identifiers, file paths, type names, commands, and status codes are code-domain
technical nouns. Apply this grammar whenever one appears in template prose:

- **Backticks, no inflection.** Write `getUser`, `null`, `OrderService`. Not
  "the `getUser`s" or "two `null`s". Acronym plurals: `APIs`, not `API's`.
- **One name per item (Rule 1.11).** Name a symbol the same way in one thread:
  `getUser`, not "the getter", then "that helper".
- **Articles.** "the" for a specific instance, "a"/"an" for an indefinite one,
  no article for a plural general reference: "The `UserController` handles a
  request. Pods run in a namespace."
- **Possessive only for roles/orgs (category 11).** "the user's session data"
  but "the configuration of the `Docker` container", not "the `Docker`
  container's configuration".
- **Capitalization.** Proper nouns keep theirs (`TypeScript`, `PostgreSQL`);
  common technical nouns are lowercase unless first word (`controller`,
  `endpoint`, `middleware`).
- **Quoted keywords and status codes (category 10).** `if`, `return`, `class`
  and codes like `404 Not Found`, `500` are quoted text: "Return `500 Internal
  Server Error`", not a bare "500".

---

## Template selection

| Situation | Template |
|-----------|----------|
| One line or one hunk in a diff | T1 — Inline review comment |
| A defect the author must fix before merge | T2 — Blocking review finding |
| An optional improvement | T3 — Non-blocking suggestion |
| Summary on the whole pull request | T4 — PR review summary |
| PR description the author writes | T5 — PR description |
| Reply to review feedback | T6 — Author response |
| Setup / install / build steps | T7 — README procedure |
| API endpoint reference entry | T8 — API doc entry |
| Function / method docstring | T9 — Docstring |
| A completed change | T10 — Commit message |
| A runtime failure the user sees | T11 — Error message |

---

## T1 — Inline review comment

```text
<observation>: one sentence, one subject, present tense.
<effect>: one sentence that gives the result of the observation.
<action>: one imperative sentence.
```

> The `getUser` function returns `undefined` when `id` is `0`.
> The caller in `UserController` then reads a property of `undefined`.
> Return `null` for an unknown `id`, and check the result in `UserController`.

Constraints: imperative action (Rule 5.3); one technical noun per item (Rule
1.11); no technical noun as a verb (Rule 1.7): "Send a request to the `/users`
endpoint", not "Endpoint the request"; identifiers in backticks, uninflected.

## T2 — Blocking review finding

```text
**Finding:** <one sentence: what is wrong>
**Location:** `<path>:<line>` in `<symbol>`
**Cause:** <one sentence>
**Result:** <one sentence: what fails, and when>
**Required change:** <one imperative sentence>
```

> **Finding:** The `saveOrder` method does not validate the `quantity` field.
> **Location:** `src/orders/service.ts:142` in `OrderService.saveOrder`
> **Cause:** The method writes the request body to the database with no check.
> **Result:** A negative `quantity` value is written to the `orders` table.
> **Required change:** Reject a request when `quantity` is less than `1`.

Write the change as one imperative sentence. Do not use "must" as an intensifier
— the field label gives the obligation. `Location` names each item with one
technical noun (Rule 1.11).

## T3 — Non-blocking suggestion

```text
**Suggestion (optional):** <one imperative sentence>
**Reason:** <one sentence>
```

> **Suggestion (optional):** Move the three retry constants into `RetryPolicy`.
> **Reason:** The same three values occur in `HttpClient` and in `QueueWorker`.

Mark optional in the first word. One imperative sentence. No hedge words
("maybe", "perhaps", "just") — Rule 1.10.

## T4 — PR review summary

```text
**Decision:** Approve | Request changes | Comment
**Scope:** <one sentence: what the pull request changes>
**Blocking findings:** <count>
1. <one sentence each, with `path:line`>
**Optional suggestions:** <count>
1. <one sentence each>
**Verification:** <one sentence: what you ran or read>
```

> **Decision:** Request changes
> **Scope:** The pull request adds a rate limiter to the `/api/v1/login` route.
> **Blocking findings:** 1
> 1. `src/middleware/rateLimit.ts:58` — The limiter counts a failed request and a successful request in the same bucket.
> **Optional suggestions:** 1
> 1. Give the `WINDOW_MS` constant a unit in its name.
> **Verification:** I ran `npm test` and read the diff in `src/middleware`.

Decision is one of the three approved values — no fourth, no sentence. Each
finding line is one sentence naming its item with one technical noun (Rule 1.11).

## T5 — PR description (author)

```text
## What
<one to three sentences. One subject in each sentence.>

## Why
<one to three sentences. Give the cause, then the result.>

## How
1. <imperative sentence>
2. <imperative sentence>

## Test
- <one sentence per check, with the command in backticks>

## Risk
<one sentence. Write "None." when there is no risk.>
```

> ## What
> This pull request adds a retry to the `PaymentClient.charge` method.
> ## Why
> The payment gateway returns `503` during a deployment. The current client fails
> the order on the first `503` response.
> ## How
> 1. Add a `RetryPolicy` class with three attempts and an exponential delay.
> 2. Call `RetryPolicy.execute` from `PaymentClient.charge`.
> ## Test
> - Run `npm test -- payment` to check the new unit tests.
> - Send a request to the sandbox gateway to check the delay values.
> ## Risk
> A retry can create a duplicate charge if the gateway accepted the first
> request. The client sends an idempotency key to prevent this result.

`How` steps are all imperative (Rule 5.3). `What` and `Why` are descriptive but
still use one technical noun per item (Rule 1.11) and approved words only.

## T6 — Author response to feedback

```text
**Comment:** <link or `path:line`>
**Response:** Done | Changed | Not changed
**Detail:** <one sentence>
```

> **Comment:** `src/middleware/rateLimit.ts:58`
> **Response:** Changed
> **Detail:** The limiter now counts only a failed request in the login bucket.

One of the three approved values. No "LGTM", "nit", "wontfix", or other jargon
(Rule 1.10). `Comment` gives the item in backticks with one name each time.

## T7 — README procedure (install / configure / build)

Use the imperative only for the procedural steps. Keep one condition–command pair
per step (Rule 5.4). Name the same file, command, and variable identically across
all steps (Rule 9.4).

```text
## Setup

Clone the repository.
Install the dependencies with `npm install`.
Set the `DATABASE_URL` environment variable in `.env`.
After the dependencies install without errors, run the development server with `npm run dev`.
```

> **Non-STE:** First you need to have Node.js version 18 or higher installed then
> run `npm install` and after all dependencies finish downloading if there are no
> errors you can run `npm run build`…
> **STE:** Make sure that Node.js version 18 or higher is installed. Run `npm
> install`. After the dependencies install without errors, run `npm run build`.

Descriptive README sections (About, Features, Architecture) use declarative
sentences — they do not instruct the reader to act.

## T8 — API doc entry (endpoint reference)

Endpoint behavior is descriptive ("Returns a list of users"). The imperative
applies to setup, auth walkthroughs, and "getting started" steps. State the
condition that triggers an error before you describe the response (Rule 5.4).

```text
### GET /users

Gets the list of users.

Request:
GET /users HTTP/1.1
Authorization: Bearer <token>

Response:
200 OK — a JSON array of user records.

Errors:
If the client sends more than 100 requests per minute, the API returns a
`429 Too Many Requests` status code. The response includes a `Retry-After`
header that shows the wait time.
```

> **Non-STE:** You can authenticate by sending a POST request to `/auth/login`
> with your credentials, and you should include the returned token in the
> Authorization header.
> **STE:** Send a POST request to `/auth/login` with your credentials. Include
> the returned token in the `Authorization` header.

## T9 — Docstring (function / method)

Describe what the code does, in the active voice (Rule 3.6), not what the reader
must do. State preconditions before behavior (Rule 5.4). Use the same term as the
function signature (Rule 9.4).

```python
def get_profile(user_id: int) -> Profile:
    """Return the profile data for the given user ID.

    Query the database for the row that matches `user_id` and return
    a Profile object. If the user does not exist, raise ValueError.
    """
    return db.query(Profile).filter_by(id=user_id).one()
```

> **Non-STE:** Gets a user record. The duration in milliseconds the client shall
> await a response prior to terminating the connection attempt.
> **STE:** Gets a user record. The time in milliseconds that the client waits for
> a response before it stops the connection.

## T10 — Commit message

Subject line is imperative and completes "If applied, this commit will…"
(Rule 5.3). The body may use descriptive sentences for rationale. Use one
imperative verb for the same category of change across the project (Rule 9.4).

```text
Fix the race condition in the connection pool

The pool returned the same connection to two threads under load.
Add a lock around the checkout path so each thread gets a unique
connection. The retry test in tests/test_pool.py now passes.
```

> **Non-STE:** Fixed the race condition in the connection pool.
> **STE:** Fix the race condition in the connection pool.

> **Non-STE:** When the connection pool reaches max connections, add a mutex lock
> around pool access to prevent a race condition.
> **STE:** When the connection pool reaches its maximum capacity, add a mutex
> lock around pool access to prevent a race condition. (condition before command,
> comma after the clause — Rule 5.4)

## T11 — Error message

Describe what failed, then give a recovery instruction, separated by a period or
newline. Do not use the imperative unless you also tell the user how to recover
(Rule 5.3). One error code produces the same text every time (Rule 9.4).

```python
raise RuntimeError(
    "The port 8080 is already in use. "
    "Set a different port with the --port option."
)
```

> **Non-STE:** Port is already in use.
> **STE:** The port 8080 is already in use. Set a different port with the
> `--port` option.

> **Non-STE:** Invalid configuration file. Check the schema.
> **STE:** The configuration file failed schema validation. Check the
> `config.schema.json` file for required fields.

---

## Approved verbs for action lines

Use these code-domain technical verbs in the imperative line of any template. Use
the base form for an instruction (Rule 5.3) and the third-person form for a
statement of fact.

| Verb | Use it for |
|------|-----------|
| add | New code, a new field, a new file |
| remove | Deleted code or a deleted field |
| replace | One item exchanged for another |
| move | Code relocated with no change in behavior |
| rename | A new name for the same item |
| return | The value a function gives back |
| throw / raise | An error the code emits |
| catch / handle | An error the code accepts |
| validate | A check on input |
| reject | A refused input or request |
| call | Invocation of a function or method |
| read / write | Access to a file, field, or record |
| log | A record written to the audit trail or log |
| test | A check that runs in the test suite |

Do not use a verb from this table as a noun (Rule 1.13): "The function returns a
value", not "The return of the function".

## Forbidden words in template prose

| Forbidden | Reason | Use instead |
|-----------|--------|-------------|
| nit, LGTM, WIP, PTAL, IMO | jargon (Rule 1.10) | the full template label |
| smelly, hacky, ugly, clean | subjective, not approved (Rule 1.1) | the concrete defect |
| stuff, thing, some code | not a technical noun (Rule 1.5) | the identifier in backticks |
| leverage, utilize | not approved (Rule 1.3) | use |
| behaviour, initialise, colour | British spelling (Rule 1.14) | behavior, initialize, color |
| we should maybe possibly | hedging (Rule 1.1) | one imperative sentence |
| delete (verb) | not approved (Rule 1.1) | remove |
| execute (verb) | not approved (Rule 1.1) | run |
| compile (verb) | not approved (Rule 1.1) | build |

## Checklist before you publish

1. Each sentence has one subject.
2. Each item has one name, used every time (Rule 1.11).
3. Each identifier is in backticks and is not inflected.
4. Each action is one imperative sentence (Rule 5.3).
5. Each condition comes before its command, separated by a comma (Rule 5.4).
6. Voice is active; passive appears only when the agent is unknown (Rule 3.6).
7. Terminology is consistent across the document and the project (Rule 9.4).
8. No word from the forbidden table is present.
9. Spelling is American English (Rule 1.14).

---

## Dictionary excerpt — instruction and template words

A focused slice of the STE-Code controlled terminology (full list in
`03-dictionary.md`). UPPERCASE = approved; lowercase = not approved, use the
listed alternative. Parts of speech: (v) verb, (n) noun, (adj) adjective,
(conj) conjunction, (TN/TV) code-domain technical noun/verb.

| Word | PoS | Approved? | STE example | Non-STE to replace |
|------|-----|-----------|-------------|--------------------|
| ADD | (v) | ✓ | Add 5 lines of configuration to the file. | Append 5 lines of configuration to the file. |
| AFTER | (conj) | ✓ | After you deploy the update, do a smoke test. | Following deployment of the update, do a smoke test. |
| BEFORE | (conj) | ✓ | Before you run the migration, read the release notes. | Prior to running the migration, read the release notes. |
| CHECK | (n) | ✓ | Do a check of the input values. | Validate the input values. |
| CHECK | (v) | ✗ | Do a check of the values. / Verify the data integrity. | Check the values. |
| CLICK | (v) (TV) | ✓ | Click the "Submit" button. | Press the "Submit" button. |
| CREATE | (v) | ✓ | Create a new instance of the class. | Instantiate a new object of the class. |
| DELETE | (v) | ✗ | Remove the file from the directory. | Delete the file from the directory. |
| IF | (conj) | ✓ | If the status code is 500, retry the request. | In the event of a 500 status code, retry the request. |
| INSTALL | (v) | ✓ | Install the package with npm. | Set up the package with npm. |
| MAKE | (v) | ✓ | Make a copy of the file. | Create a copy of the file. |
| OPEN | (v) | ✓ | Open the file for reading. | Read the file. |
| REMOVE | (v) | ✓ | Remove the deprecated function. | Delete the deprecated function. |
| REPLACE | (v) | ✓ | Replace the old library with the new one. | Swap the old library for the new one. |
| RUN | (v) | ✓ | Run the script from the terminal. | Execute the script from the terminal. |
| SAVE | (v) | ✓ | Save the file to disk. | Write the file to disk. |
| SELECT | (v) | ✓ | Select the database from the list. | Choose the database from the list. |
| SET | (v) | ✓ | Set the variable to 10. | Assign 10 to the variable. |
| TYPE | (n) (TN) | ✓ | The type of the variable is string. | The variable is a string. |
| USE | (v) | ✓ | Use the API to fetch data. | Utilize the API to fetch data. |
| WHEN | (conj) | ✓ | When the build finishes, deploy the artifact. | After the build finishes, deploy the artifact. |

Key mapping notes for template authors:

- **execute → run**, **compile → build**, **delete → remove**, **create → make**,
  **instantiate → create**, **assign → set**, **utilize/leverage → use**,
  **press (UI) → click**, **choose → select**, **swap → replace**, **validate
  (verb) → do a check / verify**, **write (file) → save**.
- Prepositions **IF / WHEN / AFTER / BEFORE** are approved for condition and
  sequence clauses (Rule 5.4). Keep the comma between the clause and the command.
- **CHECK** is approved as a noun with "do a check of"; do not use it as a verb.
- **TYPE** is a technical noun for a data type; do not use it as a verb
  ("type the command" → "enter the command").

---

<!-- 05-grammar.md -->

# Level 3 — Grammar

Grammar layer of STE-Code: the parts of the standard that constrain **form** —
word class, verb form, sentence shape, punctuation, and word count.
Vocabulary (which words you may use) is in `03-dictionary.md`; this file is
about how approved words are combined.

Scope: all code documentation — README files, API reference, docstrings, inline
comments, commit messages, error and log messages, changelogs, configuration
comments, specifications. Source code itself and the contents of fenced code
blocks are **out of scope**.

## Quick contract for a generator

| Constraint | Value |
|---|---|
| Approved verb forms | infinitive, imperative, simple present, simple past, simple future, past participle **as adjective only** |
| Forbidden verb forms | perfect, progressive, perfect-progressive, gerund-as-verb, auxiliary + past participle |
| Voice | active; passive only in descriptive text when the agent is unknown |
| Procedural sentence | max 20 words |
| Descriptive sentence / note | max 25 words |
| Instructions per sentence | 1 |
| Topics per sentence | 1 |
| Sentences per paragraph | max 6, one topic per paragraph |
| Technical noun length | max 3 words |
| Semicolon | forbidden — split into two sentences |
| Contractions | forbidden — write words in full |
| Phrasal verbs | forbidden unless explicitly approved |
| Articles | required before nouns; omitted before identifiers and abstract concepts |

## 1 — Words and parts of speech

**1.1 Use approved words only.** A word is usable if it is approved in the
controlled terminology, or is a code-domain technical noun, or is a code-domain
technical verb. Nothing else.

**1.2 Use an approved word only as its approved part of speech.** The
dictionary fixes the class. `TEST (n)` is not a licence to write "test the
build" unless `TEST (v)` is also approved.

**1.3 Use an approved word only with its approved meaning.** Approved words
normally carry exactly one meaning. Other standard-English senses are excluded.

**1.4 Use only the approved forms of verbs and adjectives.** See section 3.

**1.5 Technical nouns may be added by category.** A code-domain technical noun
names a specified software concept in a subject field (codebase, framework,
ecosystem). The controlled terminology cannot list them all; add them to the
project glossary, API reference, or ADRs, and only inside an approved category.

**1.6 An unapproved word is permitted only when it is (or is part of) a
code-domain technical noun.** Never as ordinary prose.

**1.7 Do not use technical nouns as verbs.**

> Do not write: The service *databases* the record.
>
> Write: The service writes the record to the database.

**1.8 Prefer technical nouns already approved in your project, company,
industry, or subject field** over invented ones.

**1.9 When you must coin a technical noun, make it short and clear** — not more
than three words. Add one or two adjectives only when the context does not
disambiguate.

> Do not write: Delete the four deprecated middleware registration statement entries that bind the request route to the legacy cover module.
>
> Write: Delete the four handler entries (lines 10–14) that bind the route to the cover module.

**1.10 Do not use regional words, slang, or jargon as technical nouns.**

**1.11 Do not use different technical nouns for the same item.** One item, one
name. Do not alternate `configuration file`, `settings file`, and `config`.

**1.12 Technical verbs may be added by category.** A code-domain technical verb
names a specified operation or process in software development.

**1.13 Do not use technical verbs as nouns.**

> Do not write: Run a *deploy* of the service.
>
> Write: Deploy the service.

**1.14 Use American English spelling** unless a project specification, style
guide, or contract directs otherwise. Do not change the spelling of quoted
text — error strings and UI labels stay verbatim.

### Approved technical verb categories

| Category | Verbs |
|---|---|
| Development operations | build, compile, test, lint, format, commit, push, deploy, rollback |
| Data operations | read, write, serialize, deserialize, parse, encode, decode, query, insert, migrate |
| Application operations | handle, route, authenticate, authorize, validate, schedule, dispatch, resolve |
| Communication actions | send, receive, publish, subscribe, stream, poll, broadcast, connect |

Prefer the plain approved verb — use, start, stop, show, make, get, set, check,
do, send, remove, keep — over *utilize*, *leverage*, *employ*, *commence*,
*terminate*, *initiate* when the simple verb already carries the meaning.

## 2 — Noun phrases

**2.1 Keep technical nouns short** — maximum three words. Split longer strings
with prepositions (of, on, in, for, to).

> Do not write: Request handler timeout retry policy value.
>
> Write: The retry policy for the timeout of the request handler.

**2.2 Write a long technical noun in full**, then make it usable by one of:

- Give a shorter form after the first full occurrence.
- Hyphenate the words that act as one unit.
- Split the noun with prepositions.

A term that comes from an official source (an API specification, a schema, an
OpenAPI file, an architecture diagram) is written in full at first occurrence,
explained, and then abbreviated for the rest of the document. Terms fixed by
your framework or subject field stay as they are.

**2.3 Use hyphens between words used as one unit.** See Rule 8.2 for the five
hyphenation categories and Rule 8.7 for their word count.

## 3 — Verbs

**3.1 Use only the verb forms that the dictionary gives.** Every approved verb
lists four forms in this order: base, third-person singular, simple past, past
participle.

```
VALIDATE (v)
VALIDATES
VALIDATED,
VALIDATED

BUILD (v)
BUILDS
BUILT,
BUILT
```

**3.2 Use only these forms and tenses.**

| Verb | Imperative | Simple present | Simple past | Simple future | Past participle (adjective) |
|---|---|---|---|---|---|
| (to) parse | Parse the file | It parses | It parsed | It will parse | the parsed file |
| (to) write | Write the log | It writes | It wrote | It will write | the written log |
| (to) build | Build the image | It builds | It built | It will build | the built artifact |
| (to) send | Send the request | It sends | It sent | It will send | the sent request |
| (to) validate | Validate the token | It validates | It validated | It will validate | the validated token |

Not approved: present perfect (has parsed), past perfect (had parsed),
progressive (is/was parsing), future progressive (will be parsing), perfect
progressive (has been parsing), gerund used as a verb (keeps parsing), and all
other complex constructions.

Selection:

1. Infinitive after a modal or to state a purpose — "Use this flag to parse the file."
2. Imperative for each procedure step — "Parse the file. Write the log."
3. Simple present for a fact or system behavior — "The parser reads the file."
4. Simple past for a completed action — "The build failed."
5. Simple future with `will` + base form — "The job will start at 02:00."
6. Past participle only as an adjective before a noun — "the deprecated method."

Repairs:

| Unapproved | Approved |
|---|---|
| has parsed | parsed |
| had parsed | simple past, split into two sentences with "Then" |
| is parsing / was parsing | simple present or simple past |
| will be parsing | will parse |
| is being parsed | name the actor: "the worker parses the file" |

**3.3 Use the past participle as an adjective**, not as part of a verb.

**3.4 Do not use auxiliary verbs to build complex verb constructions.** Do not
combine have, be, will, can, must, should, or "is to be" with a past participle
to make compound tenses or the passive voice.

> Do not write: The build has compiled the module before the test runs.
>
> Write: The build compiled the module. Then the test runs.
> Do not write: The migration is to be run before you deploy the service.
>
> Write: Before you deploy the service, run the migration.
> Do not write: The cache can be cleared.
>
> Write: You can clear the cache.

**3.5 Use an "-ing" form only as a technical noun or as a modifier inside a
technical noun** — never as a verb. Approved "-ing" words include the nouns
logging, monitoring, routing, servicing; the adjectives matching, missing,
remaining; the pronoun something; and the preposition during. The progressive
tense is excluded because it is not in the Rule 3.2 list.

**3.6 Use the active voice.** In descriptive text the passive is permitted only
when the agent is unknown. Test a sentence by asking "by whom or by what?" — if
the sentence answers it, it is passive.

> Do not write: The API response is parsed by the middleware.
>
> Write: The middleware parses the API response.

**3.7 Describe an action with an approved verb, not a noun.**

> Do not write: Validation of the token happens in the handler.
>
> Write: The handler validates the token.

## 4 — Sentences

**4.1 One topic per sentence. No abstract text.** Do not combine multiple
actions, conditions, or subjects.

**4.2 Do not omit words and do not use contractions.** Keep the subject, the
verb, the nouns, and the articles. Write "do not", "is not", "are not" — never
"don't", "isn't", "aren't". A shorter sentence is not automatically clearer.

> Do not write: Can be a maximum of five inches long.
>
> Write: A cache key can have a maximum length of 64 characters.

**4.3 Use a vertical list for complex text.** Use a list when a sentence must
carry many items — parameters, return fields, error codes, configuration
options, environment variables, dependencies, test cases.

- Put a colon at the end of the introductory sentence.
- Mark each item with a number, letter, dash, or bullet.
- Start each item with an uppercase letter.
- Use an article before the subject noun of an item where applicable.
- End a full-sentence item with a period; an imperative step is a full sentence.
- Do not end a fragment item with a period, a comma, or a semicolon.
- Put a period at the end of the last item.

Do not mix imperative instructions and descriptive statements in one list. In
safety instructions, write the negative command (DO NOT) inside each item that
needs it.

**4.4 Use connecting words and connecting phrases.** Approved connectors:
`and`, `but`, `then`, `thus`, `also`, `however`, `therefore`, `for example`,
`as a result`, `at the same time`. Place the connector at the start of the
sentence so the reader sees the signal before the content. Do not use
*moreover*, *furthermore*, *nevertheless*, or *subsequently*. Demonstrative
adjectives (this, these) may also connect a sentence to the one before it.

**4.5 Use an article or a demonstrative adjective before a noun.**

- Use an article before each noun in a short sentence.
- In a series, use the article before the first noun only — unless an adjective
  applies to one item only, in which case repeat the article.
- Do not use an article before an abstract concept: performance, scalability,
  error handling, concurrency, backward compatibility.
- Do not use a definite article before a code identifier. A function, class,
  variable, file name, environment variable, error code, and version tag are
  proper nouns.
- Always keep the noun after `this` or `these`. Never write `this` alone.

## 5 — Procedures

**5.1 Maximum 20 words in a procedural sentence.** This covers installation
steps, setup guides, deployment checklists, debugging workflows, and API usage
guides. Warnings and cautions obey the same limit. Notes may reach 25 words.
Code blocks, command examples, terminal output, string literals, and identifier
names inside examples are excluded from the count.

> Do not write: Run the database migration script from the project root directory and then restart the application server to apply all pending schema changes to the production environment. (27 words)
>
> Write: Run the database migration script from the project root directory. Then restart the application server. (9 + 7 words)

**5.2 One instruction per sentence.** If a step contains two actions, write two
sentences or two numbered steps.

**5.3 Use the imperative form for instructions.** "Set the timeout value." Not
"The timeout value should be set."

**5.4 Put the descriptive statement before the command.** Give the condition
first, then the action, so the reader knows when the step applies.

**5.5 Notes give information only.** A note must not contain an instruction, a
command to run, a step, or an imperative verb. It must not give requirements,
limits, tolerances, or expected results of a step — that information belongs in
the step itself. Move anything critical for data loss, security, or system
damage into a WARNING or CAUTION. Each note sentence has a maximum of 25 words.

Verification: read the procedure without the notes. If the reader cannot
complete it, the missing information belongs in a step.

> NOTE: The API rate limiter allows a maximum of 1000 requests per minute per client IP address on the free tier.

## 6 — Text structure

**6.1 Give information gradually.** One subject per sentence. Do not pack a
request lifecycle, an error path, and a logging side effect into one sentence.

**6.2 Use key words and key phrases to give the text a logical structure.** Key
words repeat across a documentation block and link its concepts. Do not vary
them. Connecting words act as traffic signs: they tell the reader whether the
information is new, contrasting, or a result.

**6.3 Write short sentences — maximum 25 words in descriptive text.**
(Procedural text keeps the 20-word limit of Rule 5.1.)

**6.4 Use paragraphs to show related information.**

**6.5 One topic per paragraph.**

**6.6 Maximum six sentences per paragraph.**

## 7 — Safety instructions

**7.1 Use a signal word to show the level of risk.**

| Signal word | Use when | Release-note / changelog mapping |
|---|---|---|
| WARNING | Risk of security vulnerability, data loss, or system corruption | BREAKING |
| CAUTION | Risk of unexpected behavior, performance degradation, or incorrect results | DEPRECATED |
| NOTE | Supplementary information only | NOTE |

If both risk levels apply together, use WARNING.

**7.2 Start a safety instruction with a clear and accurate command or
condition.** If the reader must know a condition before using a function,
method, or API, give the condition first.

> Do not write: WARNING: STORING API KEYS IN THE SOURCE CODE IS NOT RECOMMENDED.
>
> Write: WARNING: DO NOT STORE API KEYS IN THE SOURCE CODE. USE ENVIRONMENT VARIABLES OR A SECRETS MANAGER.

**7.3 Explain the risk or the possible result.** A risk explanation has three
parts: the failure to obey the instruction, the immediate consequence, and the
final harm. Write it cause-first: "If you do X, Y can happen." An instruction
without a risk explanation is a prohibition the reader can dismiss.

> WARNING: DO NOT STORE API KEYS IN THE SOURCE CODE. API KEYS IN SOURCE CODE CAN CAUSE UNAUTHORIZED ACCESS AND DATA BREACHES.

## 8 — Punctuation and word count

**8.1 Use all standard English punctuation except the semicolon.** The
semicolon lets you build long sentences that are hard to read in comments and
docs, and it is easy to misuse. Write two sentences instead. The rule does not
apply to source code or to text inside code blocks, where the semicolon is
language syntax.

> Do not write: Call the function to parse the response data; handle any errors that occur.
>
> Write: Call the function to parse the response data. Handle any errors that occur.

**8.2 Use hyphens to connect words that are directly related.** Five categories:

| Category | Code-domain examples |
|---|---|
| 1. Multi-word adjective before a noun | high-priority task, read-only file, thread-safe method, event-driven architecture, run-time error, end-to-end test, server-side rendering, just-in-time compilation |
| 2. Two-word fractions and numbers | seventy-two, one hundred and twenty-eight, three-fourths |
| 3. Uppercase letter or number plus a noun (shape or configuration) | L-shaped bracket, T-shaped connector, 64-bit register, 8-byte alignment, 128-bit value |
| 4. Verb whose first part is a noun or other part of speech | dry-run, hot-reload, cold-start, hard-code, soft-delete, short-circuit |
| 5. Prefix ending in a vowel before a root starting with a vowel | pre-initialized, re-entrant, de-allocated, anti-aliasing, re-indexed |

A hyphen joins words into one concept. A dash separates ideas or shows a range
("lines 12–48"). Keep them distinct.

**8.3 Use parentheses** to:

- Make references to code modules, diagrams, or text
- Include letters or numbers that identify items
- Identify the work steps in a procedure
- Include abbreviations
- Give the singular and plural forms of a noun at the same time
- Explain a word or part of a sentence
- Include an alternative.

**8.4 A colon in a vertical list counts as a period.** It marks the end of a
sentence. So the introductory part before the colon takes a maximum of 20 words
in procedural text and 25 words in descriptive text, and each item after the
colon counts as a new sentence with the same limits.

**8.5 Text in parentheses counts as one word** in the sentence that contains
it. The words inside the parentheses also form their own sentence, so count
them there. An identifier or an abbreviation in parentheses counts as one word.

> Write: Make sure that the DEBUG environment variable is set to false (the DEBUG flag is off). (12 words)

**8.6 Count each of these as one word:**

- Numbers
- Numbers together with units of measurement
- Abbreviations
- Alphanumeric identifiers
- Quoted text
- Titles, headings, and text on user interface elements and labels
- Proper nouns of individuals, groups, organizations, and geopolitical entities.

**8.7 A hyphenated word counts as one word.** A group of words hyphenated to act
as an adjective before a noun is one unit for the word-count limits.

> Do not write: The open function returns a read only file descriptor.
>
> Write: The open function returns a read-only file descriptor. ("read-only" = one word)

## 9 — Applying the standard

**9.1 Use a different sentence construction when a word-for-word replacement is
not sufficient.** When a word is unapproved, the dictionary gives alternatives.
Replace word-for-word only when the part of speech matches and the meaning does
not change. Rewrite the sentence when:

1. The grammatical structure must change to use the alternative.
2. The replacement gives a meaningless or unclear result.
3. The alternative changes the meaning.
4. The word to replace is not in the controlled terminology.

Then think about the purpose of the sentence: select different words, change
the verb form, write shorter sentences, remove unnecessary information, or ask
a developer for more information.

**9.2 Use each approved word correctly.** Read the approved meaning before you
use a word. Approved words normally have one approved meaning and one approved
part of speech. A small number are approved as more than one part of speech.

**9.3 Do not make phrasal verbs.** Two individually approved words can combine
into a phrasal verb whose meaning is different from its parts. Replace it with
a single approved verb. Only a few phrasal verbs are approved, and they have a
restricted meaning.

| Phrasal verb | Approved verb |
|---|---|
| put out (a warning) | emit |
| give off | release |
| carry out (a test) | do |
| shut down | stop |
| set up | configure |

> Do not write: The compiler puts out a warning when the type annotation is missing.
>
> Write: The compiler emits a warning when the type annotation is missing.

**9.4 Use a consistent style for terminology and wording.** The same type of
step gets the same wording every time. Use one name for one item (not
"configuration file", "settings file", and "config"). Use one verb for one
action (not "compile", "build", and "make"). Use the same sentence structure
for the same type of instruction.

> Do not write: Apply the patch to the main module. Wipe the module clean. Inspect the module assembly for errors.
>
> Write: Apply the patch to the module. Clean the module. Check the module for errors.

---

<!-- rules-sec1-part1.md -->

# Level 3 — STE-Code Section 1 Rules, Part 1 (Words)

LLM-optimized distillation of the STE-Code controlled standard, Section 1 (Words).
This document covers the vocabulary-control rules for code documentation:
which words you may use, how to use them, and how to spell them.

Scope of this slice:
- Rule 1.1 — Approved words, technical nouns, technical verbs (the three-gate model)
- Rule 1.2 — Approved words only as their specified part of speech
- Rule 1.3 — Approved words only with their approved meanings
- Rule 1.4 — Only approved verb and adjective forms
- Rule 1.10 — No slang, jargon, or regional terms
- Rule 1.11 — One term per concept (consistency)
- Rule 1.12 — Technical verbs are allowed (category list)
- Rule 1.13 — Do not use technical verbs as nouns
- Rule 1.14 — American English spelling

It is self-contained: every rule below is stated plainly with code-domain examples.
For the full controlled terminology (dictionary) and the 19 technical-noun categories,
see `a-dictionary.md` and `a-categories.md` in the same artifact set.

## Principle legend (recurs in the examples)

These codes label the fix applied in each before/after pair:
- P1 — use an approved word from the controlled terminology
- P2 — use the approved part of speech
- P3 — use the approved meaning of the word
- P4 — use only approved verb/adjective forms (no "-ing" main verbs, correct tense/mood)
- P6 — quoted text (code, keywords, third-party output) is exempt and kept as-is
- P7 — do not use a technical noun as a verb
- P8 — use standard, well-known technical nouns
- P9 — prefer short, clear technical nouns
- P10 — no slang / jargon / metaphor
- P11 — one term per concept
- P12 — technical verbs allowed only when no approved verb fits
- P13 — do not use a technical verb as a noun
- P14 — American English spelling

---

## Rule 1.1 — Use Words That Are Approved in the Dictionary, Technical Nouns, or Technical Verbs

Every word in code documentation must pass one of three gates:

1. **Approved word** — listed in the STE-Code controlled terminology (Part 2), used with its
   specified part of speech (Rule 1.2) and approved meaning (Rule 1.3).
2. **Code-domain technical noun** — not in the terminology (or listed UNAPPROVED) but fits one
   of the 19 technical-noun categories (Rule 1.5). Names a specific concept, component, tool, or
   entity in software (e.g. `UserAuthenticator`, `Promise`, `kubectl`). A word that passes here
   must not be used as a verb (Rule 1.7).
3. **Code-domain technical verb** — not in the terminology but names a specific software operation
   (Rule 1.12), e.g. `serialize`, `refactor`, `lint`. A word that passes here must not be used as a
   noun (Rule 1.13).

A word that passes none of the three gates must be replaced with an approved alternative or the
sentence restructured.

Applies to all documentation types (README, API docs, docstrings, commit messages, error messages).
In each type, imperative verbs must come from the approved list.

Short substitutions to internalize:
- "execute" → `run` · "generate" → `make` · "configure" → `set` · "utilize/leverage" → `use`
- "retrieve/fetch" → `get` · "transmit" → `send` · "delete/purge" → `remove` · "verify" → `check`
- "unable to" → `cannot` · "invalid" → `not correct` · "commence/initiate" → `start` · "terminate" → `stop`
- "implement" → `make`/`add` (not approved as a verb) · "optimize" → `make faster`/`make smaller`

Example (README setup):
> Non-STE: To begin utilizing the build toolchain, you must first generate the distributable
> artifact via `npm run build`. Then, execute the compiled binary to bootstrap the local
> development service.
> STE: Use the build tool to make the binary. Run the binary to start the local service.

Example (API docstring):
> Non-STE: Fetches a user record from the remote API.
> STE: Gets a user record from the remote API.

See also: Rules 1.2–1.14, and `a-dictionary.md` / `a-categories.md`.

---

## Rule 1.2 — Use Approved Words Only as the Specified Part of Speech

Each approved word in the controlled terminology carries a part-of-speech label
(verb, noun, adjective, adverb, preposition, conjunction, pronoun, article). Use it only in that role.

Most common violations:
- **Noun-as-verb** — a tool/library/data-structure name used as a verb.
  `Docker the app` → `Use Docker to make a container` · `Git the change` → `Save the change with Git`
  `Cache the result` → `Keep the result in the cache` · `Query the database` → `Send a query to the database`
- **Adjective-as-verb** — `Secure the endpoint` → `Make the endpoint secure` ·
  `Empty the buffer` → `Make the buffer empty` (note: `clear` IS approved as both, so `Clear the flag` is fine)

Preferred approved verbs to replace inflated or misused forms:
- "utilize/leverage/employ" → `use` · "commence/initiate" → `start` · "terminate" → `stop`
- "orchestrate" → `control` · "facilitate" → `help`

The fix patterns:
1. Prepositional phrase: `Git the changes` → `Save the changes with Git`
2. Infinitive: `Queue the jobs` → `Use the queue to hold the jobs`
3. Make + adjective: `Secure the endpoint` → `Make the endpoint secure`

A word approved as more than one part of speech (e.g. `call`, `set`, `clean`) is valid in each role,
but the sentence structure must make the role clear. If a word appears twice with different roles,
restructure (e.g. use "change history" instead of "commit history" to avoid double "commit").

Exceptions:
- Code-domain technical verbs under Rule 1.12 override this rule for that specific word/context
  (e.g. `serialize` is permitted as a verb even though not in the general approved list).
- Quoted code/CLI commands in code blocks are exempt (Rule 1.5, category 10).

Examples:
> Non-STE: Query the database for user records.
> STE: Send a query to the database for user records.
>
> Non-STE: Static the variable to prevent modification.
> STE: Make the variable static to prevent modification.
>
> Non-STE: refactor: interface the user repository and factory the database connection
> STE: refactor: add an interface to the user repository and use a factory for the database connection

Command/keyword edge case: `return` is an approved verb ("send a value back from a function") —
`Return the result` is fine. `import`/`export` are NOT approved verbs — use
`Use \`import\` to add the module` / `Use \`export\` to make the function available`.

See also: Rules 1.1, 1.3, 1.4, 1.5, 1.7, 1.10, 1.12, 1.13.

---

## Rule 1.3 — Use Approved Words Only with Their Approved Meanings

Each approved word has exactly ONE approved meaning in the controlled terminology. Using the right
word with the wrong meaning is a violation even when the sentence is grammatical.

Decision procedure before publishing:
1. Identify the part of speech you used (Rule 1.2 selects the meaning).
2. Look up the approved meaning for that part of speech in `a-dictionary.md`.
3. Does your sentence use it with exactly that meaning? If no, it fails.
4. Replace with an approved word whose meaning fits, or restructure.

Most-misused approved words (use only the approved meaning):

| Word | Approved meaning | Wrong meaning to avoid → use instead |
|------|------------------|--------------------------------------|
| run | execute a program or command | operate/manage/continue → `operate`/`continue` |
| return | send a value back from a function to its caller | go back to a state/location → `go back` |
| call | invoke a function/method | name something → `name` |
| get | fetch or retrieve data from a source | become/understand → `become`/`understand` |
| set | put a value into a variable/config | become solid/prepare → `become solid`/`prepare` |
| make | bring into existence by building | force/earn → `cause`/`earn` |
| send | transmit data to a destination | cause a person to go → `cause to go` |
| raise | cause an exception to occur | increase/lift → `increase`/`lift` |
| catch | handle or intercept an exception | capture a moving object → `capture` |
| pass | give data as an argument to a function | go past/succeed → `go past`/`succeed` |
| check | examine for correctness or state | stop/restrain → `stop`/`leave` |
| break | exit a loop/switch immediately | divide into parts/damage → `split`/`damage` |
| continue | skip to next loop iteration | keep doing without interruption → `keep` |
| fail | an operation did not complete | not pass a test → `not pass` |
| move (Rust) | transfer ownership of a value | change physical position → `go`/`change position` |
| borrow (Rust) | take a reference without ownership | take temporarily → `take temporarily` |

Paradigm-specific meanings matter: e.g. in OOP `extend` = "create a subclass", `override` = "replace an
inherited method"; in functional `map` = "transform each element", `reduce` = "combine into one value",
`pure` = "no side effects"; in declarative SQL `select` = "retrieve rows" (not "choose"), `drop` =
"remove a table permanently"; in systems `own`/`borrow`/`move`/`drop` carry Rust ownership meanings.

Examples:
> Non-STE: This tool runs on Node.js and runs in the browser.
> STE: This tool operates on Node.js and operates in the browser. (first two "runs" = operates)
>
> Non-STE: Raises the value by 10% and passes it through the pipeline.
> STE: Increases the value by 10% and sends it through the pipeline.
>
> Non-STE: refactor: break the UserService into smaller classes
> STE: refactor: split the UserService into smaller classes  ("break" = exit a loop, not divide)

Edge case — multiple approved meanings: `set`, `run`, `file`, `test` have >1 approved meaning tied to
part of speech; `call` means "invoke" (verb) vs "invocation" (noun). Use "name", not "call", for
"we call this pattern X". Edge case — framework name shares spelling with an approved word
(`Express` the framework vs `express` the verb): capitalize the framework, do not use it as a verb.

See also: Rules 1.1, 1.2, 1.4, 1.7, 1.11, 1.13.

---

## Rule 1.4 — Use Only the Approved Forms of Verbs and Adjectives

The controlled terminology lists the approved inflected forms of each approved verb and adjective.
Use only those forms.

Verbs: use the imperative/base form for procedures, simple present (3rd-person `-s`) for descriptions,
simple past for completed actions. **Do not use the "-ing" form as the main verb of a procedural or
descriptive sentence** — this is the most common Rule 1.4 violation. Concentrate tenses: simple
present, simple past, simple future; not present/past perfect continuous.

Example approved verb table:

| Verb | Imperative | 3rd-person | Past | Past participle (adj) | Non-approved |
|------|-----------|------------|------|------------------------|--------------|
| make | Make | Makes | Made | Made | Making, Maked |
| get | Get | Gets | Got | Got (past only) | Getting, Getted |
| set | Set | Sets | Set | Set | Setting, Setted |
| call | Call | Calls | Called | Called | Calling |
| check | Check | Checks | Checked | Checked | Checking |
| give | Give | Gives | Gave | Given | Giving, Gived |
| run | Run | Runs | Ran | Run | Runned, Running (as main verb) |

Adjectives: use the dictionary-listed comparative/superlative forms (`fast`→`faster`/`fastest`,
`slow`→`slower`/`slowest`). Do not use "more fast" / "more slow". Adjectives that form comparatives
with `more`/`most` use those approved words instead. Do not invent forms like "compilating",
"membered", "performant".

Examples:
> Non-STE: The compiler is compilating the source files every time you save.
> STE: The compiler compiles the source files each time you save.
>
> Non-STE: This algorithm is more fast than the previous one.
> STE: This algorithm is faster than the previous one.
>
> Non-STE: Fixed memory leak and adding timeout configuration
> STE: Fix memory leak and add timeout configuration  (commit subjects: imperative, base form)
>
> Non-STE: Connection failed: the database is not running. Please verify and retrying the migration.
> STE: Connection failed: the database does not run. Check and try the migration again.

Code-domain technical verbs (Rule 1.12) follow standard English morphology and are exempt from the
closed approved-verb list, but still obey the tense/mood constraints (no "-ing" main verbs, correct
tense). `run` is irregular (run/runs/ran/run); `give` (give/gives/gave/given).

See also: Rules 1.1, 1.2, 1.3.

---

## Rule 1.10 — Do Not Use Regional, Slang, or Jargon Words as Technical Nouns

Use well-known words. Avoid regional terms (ecosystem-specific vocabulary), slang (metaphorical or
casual verbs), and jargon (community-dependent fuzzy terms) — even when they name a "concept".

Replace jargon with plain approved words:
- `cruft` → `unnecessary code` · `monkeys with` → `changes` · `grok` → `understand`
- `yak shaving` → `completing unrelated prerequisite tasks`
- `bikeshedding` → `unnecessary discussion about small details`
- `foo`/`bar` → `example`/`placeholder` · `pear-shaped` → `failed`
- `yeet` → `remove` · `dumpster fire`/`nuke` → state problem + action plainly
- `nerfed` → `decreased performance` · `shiny new hotness` → `current interface`
- `twiddle`/`tweak` → `change`/`set` · `pwn` → `control`

Community abbreviations that transcended jargon stay as technical nouns: `API`, `JSON`, `SQL`, `HTML`.
Less-universal ones remain jargon: `AFAICT`, `IIRC`, `IMHO` — spell out or omit. Initialisms that encode
principles (`DRY`, `KISS`, `YAGNI`) are jargon abbreviations; state the principle directly.

Temporal jargon has no fixed meaning: `modern`, `legacy`, `cutting-edge`, `state-of-the-art` → describe
the specific characteristic (`uses async/await`) or date (`written in 2018`).

Examples:
> Non-STE: Remove all the cruft from the legacy module.
> STE: Remove all the unnecessary code from the legacy module.
>
> Non-STE: I spent the morning yak shaving before I could write the test.
> STE: I spent the morning completing unrelated prerequisite tasks before I could write the test.
>
> Non-STE: This library lets you pwn the DOM.
> STE: This library lets you control the DOM.
>
> Non-STE: Replace the foo and bar placeholders with real values.
> STE: Replace the example and placeholder values with real values.
>
> Non-STE: The upload went pear-shaped halfway through.
> STE: The upload failed at 50 percent. Check your network connection and try again.

Paradigm slang to avoid: OO `POJO-ify`/`bean-ize` → `convert to a plain object`; FP `eta-reduce` →
`simplify the function`; procedural `massage the buffer` → `adjust the buffer`; declarative
`cattle not pets` → `disposable resources`; systems `UB`/`UAF` → `undefined behavior`/`use-after-free`
(spell out on first use).

Review checklist: (1) would a developer from another country understand every word? (2) replace
metaphors/idioms with literal descriptions; (3) expand abbreviations on first use; (4) replace
community nicknames with standard terms; (5) replace temporal words with dates/characteristics;
(6) verify every noun/verb is approved or a justified technical noun; (7) no slang verbs
(`hit`, `nuke`, `yeet`, `tweak`, `twiddle`).

See also: Rules 1.1, 1.5, 1.6, 1.11, 1.12, 1.13, 1.14.

---

## Rule 1.11 — Do Not Use Different Technical Nouns for the Same Item

Pick one code-domain technical noun for each component, service, module, endpoint, class, function,
table, resource, environment variable, or configuration key — and use it consistently everywhere.
The source of truth is the code itself (the class/function/module/table/resource name as defined in
the repo). Do not drift to colloquial synonyms.

Examples:
> Non-STE: Initialize the UserService class ... Call the authenticate method on the AccountManager ...
>          The UserHandler returns a session token.
> STE: Initialize the UserService class ... Call the authenticate method on the UserService ...
>       The UserService returns a session token.
>
> Non-STE: Send a request to the /api/login path ... The authentication route returns a JSON Web Token ...
> STE: Send a request to the /api/login endpoint ... The /api/login endpoint returns a JSON Web Token ...
>
> Non-STE: Set the database_connection_timeout ... The DB timeout parameter ... Increase the connection deadline ...
> STE: Set the database_connection_timeout ... The database_connection_timeout parameter ...
>       Increase the database_connection_timeout value ...

Per paradigm: the canonical noun is the class name (OO), the module/function name or type alias
(functional), the function/struct/file path (procedural), the resource/table name (declarative), the
language-spec or glossary term (systems, abstract concepts). Parallel lists must use one naming
convention. When a project genuinely has multiple components, introduce each explicitly rather than
drifting names.

Grammar consequence: consistent nouns keep English article and pronoun reference chains intact
(`the UserService ... it returns` — not `the AccountManager`, which breaks anaphora).

Edge cases: framework/library names that are also approved words (`Make`, `Act`, `Before`) — use the
framework name as a technical noun, capitalize to disambiguate (`Use the Make build tool to make the
project`). Generated code symbols — use the generated name as-is, define a declared alias if long.
Renaming during refactor — after commit, update all docs to the new name; keep `DEPRECATED` marker only
if the old name persists in a public API.

See also: Rules 1.1, 1.3, 1.5, 1.6, 1.8, 1.9, 1.10, 3.1, 3.6.

---

## Rule 1.12 — You Can Use Verbs That You Can Include in a Technical Verb Category

Code-domain technical verbs are permitted even when not in the approved word list, IF they name a
specific software operation and no approved verb gives the same meaning. They obey the same tense/
mood/voice rules as approved verbs (Rule 1.4, Section 3).

**Prefer an approved verb when one fits** (e.g. `find` over `detect` when not a security context;
`run` + noun over `migrate`; `run` over `execute`; `check` over `verify`). Use the technical verb only
when precision needs it and an approved verb would be vague.

The four categories (examples — not an exhaustive list):

**1. Development processes**
- a) Write/modify code: `compile, concatenate, import, inject, instantiate, lint, minify, marshal,
  optimize, polyfill, refactor, resolve, shim, stub, substitute, tokenize, transpile, trace, vectorize`
- b) Test/verify: `assert, benchmark, debug, fuzz, instrument, mock, profile, snapshot, spy, stub, unit-test`
- c) Build/package: `bundle, deploy, package, publish, release, tag, version`
- d) Manage deps: `hoist, install, link, lock, pin, update, upgrade`

**2. Computer processes and applications**
- a) I/O: `click, copy, cut, digitize, enter, paste, press, print, scan, swipe, tap, type`
- b) UI/app ops: `clear, close, delete, deselect, disable, drag, drag and drop, enable, encrypt,
  erase, filter, hide, highlight, invalidate, maximize, minimize, navigate, open, save, scroll,
  select, show, sort, store, submit, toggle, validate, zoom in, zoom out`
- c) System ops: `abort, authenticate, authorize, boot, cache, communicate, configure, debug,
  deserialize, download, format, hydrate, initialize, install, load, log, manage, mount, process,
  reboot, render, retry, serialize, spawn, synchronize, throttle, update, upgrade, upload`

**3. Instructions for subject fields**
- a) Algorithmic/math/data: `aggregate, bisect, compute, concatenate, convert, count, decode, encode,
  escape, filter, hash, index, map, merge, normalize, parse, pipeline, precompute, recalculate,
  reduce, tokenize, transform, validate, verify`
- b) Database/storage: `backup, compact, flush, index, migrate, persist, query, replicate, restore,
  roll back, seed, shard, upsert, vacuum, write-ahead`
- c) Network/communication: `broadcast, connect, disconnect, establish, forward, handshake, intercept,
  listen, poll, proxy, reject, resolve, route, send, stream, timeout, tunnel, unsubscribe, webhook`
- d) Security/auth: `authenticate, authorize, decrypt, decode, encode, encrypt, hash, revoke, salt,
  sanitize, sign, validate, verify`

**4. Legal and licensing terms** (only for legal/regulatory text):
`acknowledge, assign, comply with, conform to, disclose, enforce, explain, grant, inform, license,
modify, notify, permit, regulate, sign, supersede, waive`

Paradigm-specific verb sets:
- OO: `instantiate, inherit, override, extend, implement, encapsulate, delegate, inject`
- Functional: `compose, curry, map, reduce, fold, recurse, memoize, lift`
- Procedural: `allocate, deallocate, dereference, flush, signal`
- Declarative: `provision, converge, reconcile, apply, destroy`
- Systems (Rust): `borrow, own, drop, move, pin, acquire, release`

Examples:
> Non-STE: If you detect broken wires, repair them.  →  STE: If you find broken wires, repair them.
> (general context: "detect" not approved → use approved `find`)
>
> Non-STE: The intrusion detection system detects unauthorized access ...  (security context)
> STE: The intrusion detection system detects unauthorized access ...  ("detect" is a technical verb here)
>
> Non-STE: migrate the database schema ... verify the row counts
> STE: run the migration of the database schema ... check the row counts  (approved verb + noun preferred)

Light-verb anti-pattern (see Rule 1.13): do not wrap a technical verb in `do/make/perform/execute`
as a noun. Multi-word technical verbs (`roll back`, `drag and drop`, `zoom in`, `write-ahead`) stay as
one unit — do not split them with an object.

See also: Rules 1.1, 1.2, 1.5, 1.7, 1.11, 1.13, Section 3.

---

## Rule 1.13 — Do Not Use Technical Verbs as Nouns

Code-domain technical verbs (Rule 1.12) must be used only as verbs, never as nouns. If you need a noun,
use an approved noun or a code-domain technical noun. The most common violation is the **light-verb
construction**: a weak verb (`do/make/perform/execute/run`) + a nominalized technical verb.

Fix: use the technical verb as the main verb.
- `Make a commit` → `Commit` · `Do a compile` → `Compile` · `Execute a deploy` → `Deploy`
- `Run a build` → `Build` (when "build" names an artifact/process, it is a dual-category noun — see below)
- `The /api/login endpoint` (noun) ✓ vs `Do a login` → `Log in`
- `merge` as noun → `merge operation` · `import` as noun → `import operation`

Dual-category words (permitted as both verb and noun because they name a concrete artifact/event):
`build` (category 3 dev tools), `deploy` (cat 5 infra), `test` (cat 3), `commit` (cat 4 data structures),
`merge` (cat 4), `release` (cat 5), `patch` (cat 4), `log` (cat 13 runtime), `import` (cat 4).
Test: if you can put `a/an/the` before it and the sentence stays grammatical AND the word names a
concrete artifact/event in a technical-noun category, it is correct (`the build failed` ✓). If not
(`the compile failed`), it is a violation.

Article test: `the lint found errors` → VIOLATION (`lint` not dual-category) → `the linter found errors`.
`the serialize failed` → VIOLATION → `the serialization failed` or `the function serializes`.

Per paradigm: OOP — `do an instantiate` → `instantiate`; functional — `do a map over the list` →
`map over the list`; procedural — `do an allocate of memory` → `allocate memory`; declarative —
`do an apply of the manifest` → `apply the manifest`; systems — `the borrow of the reference` →
`the reference borrow` (or `borrow` as noun is fine for the Rust borrow concept, but `do a borrow` is wrong).

Examples:
> Non-STE: The `build` job does a compile of the source files, then starts the unit tests.
> STE: The `build` job compiles the source files, then starts the unit tests.
>
> Non-STE: Make a commit of your changes before you switch branches.
> STE: Commit your changes before you switch branches.
>
> Non-STE: If the error rate stays above five percent, execute a rollback of the migration.
> STE: If the error rate stays above five percent, roll back the migration.

Gerunds ("compiling takes ten seconds") are permitted in descriptive text but avoid as main verbs in
procedural sentences. Generated tool output (compiler messages) is quoted text — preserve as-is.

See also: Rules 1.12, 1.5, 1.7, 1.4, 1.10.

---

## Rule 1.14 — Use American English Spelling

Default to American English spelling in all prose. Exceptions: quoted text (third-party error
messages, terminal output, UI labels, code keywords) and proper names/technical nouns keep their
original spelling. An official project style guide mandating British English overrides this rule
(document it in CONTRIBUTING.md), but then the project is outside STE-Code for spelling.

Three spelling classes:
1. **Prose words** — American English only, no exceptions.
2. **Quoted text** — preserved as-is (Rule 1.5, category 10).
3. **Code-domain technical nouns** — use official spelling; surrounding prose stays American.

Suffix rules:
- **-ize / -ise**: use `-ize` (initialize, serialize, optimize, organize, recognize, synchronize,
  standardize, parameterize, customize, authorize, analyze, paralyze). Never `-ise` in prose.
- **-or / -our**: use `-or` (color, behavior, flavor, humor, labor, neighbor, rumor, harbor, honor,
  vapor, rigor). Not `-our`.
- **-er / -re**: use `-er` (center, theater, liter, meter [measuring device], fiber, caliber). Not `-re`.
  Note: "meter" (device) ≠ "metre" (length) — code docs always use "meter".
- **-l / -ll**: single `-l` in American (canceled, traveler, modeled, labeled, signaled). Not `-ll`.
  Exception: stress-final-syllable words double in both dialects (compelled, rebelled).

Common swaps:

| British | American | | British | American |
|---------|----------|---|---------|----------|
| colour | color | | licence (n) | license |
| behaviour | behavior | | defence | defense |
| centre | center | | programme | program |
| analyse | analyze | | practise (v) | practice |
| optimise | optimize | | catalogue | catalog |
| parametrise | parameterize | | analogue | analog |
| customise | customize | | judgement | judgment |

Same spelling both dialects (do NOT "fix"): address, all, committee, disappoint, necessary,
occurrence, parallel, recommend.

Examples:
> Non-STE: The log file shows the colour of each output line.
> STE: The log file shows the color of each output line.
>
> Non-STE: Initialise the variable before you use it.
> STE: Initialize the variable before you use it.
>
> Non-STE: The terminal shows the message `Colour profile not recognised`.
> STE: The terminal shows the message `Colour profile not recognised`. (quoted text preserved)
>
> Non-STE: The ColourPicker component uses the colour library for colour space conversions.
> STE: The `ColourPicker` component uses the `colour` library for color space conversions.
> (framework names preserved; prose uses American)

Enforcement: configure spell checker to en-US; pre-commit hook; CI step rejecting British spellings;
maintain a project dictionary of British-spelled technical nouns so the checker does not flag them.

See also: Rules 1.1, 1.5, 1.11, 8.6.

---

<!-- rules-sec1-part2.md -->

# Level 3 — Words, Part 2: Code-Domain Technical Nouns (Rules 1.5–1.9)

Scope: the technical-noun block of STE-Code Section 1. Five rules decide which
words outside the approved dictionary may appear in code documentation, how they
must be spelled, shaped, and used, and which part of speech they may take.

Reading order: 1.5 defines what a code-domain technical noun is → 1.6 is the gate
that admits unapproved words → 1.7 forbids using those nouns as verbs → 1.8 picks
the standard name among competing candidates → 1.9 keeps the chosen name short.

Vocabulary model in one line: every word in STE-Code documentation is either an
approved dictionary word (Rule 1.1) or a code-domain technical noun (Rule 1.5) or
a technical verb (Rule 1.12). There is no fourth category.

---

## Rule 1.5 — You can use words that you can include in a code-domain technical noun category

**Rule.** You can use words that you can include in a code-domain technical noun
category.

A code-domain technical noun names a specified concept in software development
and is applicable to a subject field. The controlled terminology does not list
them all — there are too many, and each project uses different ones. Record the
ones your project uses in the project glossary or terminology database.

Technical nouns are permitted in procedural and descriptive writing when they fit
one or more of the nineteen categories below.

### The nineteen categories

| # | Category | Examples |
|---|---|---|
| 1 | Code components, modules, and libraries | class, controller, helper, hook, middleware, mixin, module, package, plugin, provider, repository, service, utility |
| 2 | Computing devices and their components | CPU, disk, GPU, keyboard, laptop, memory, monitor, mouse, printer, screen, server, smartphone, tablet, terminal |
| 3 | Development tools, environments, and support equipment | CLI, compiler, debugger, Docker, editor, IDE, Git, Jest, linter, loader, Prettier, terminal, test runner, TypeScript, webpack |
| 4 | Data structures, types, and formats | array, boolean, buffer, CSV, enum, hash map, integer, JSON, linked list, object, queue, stack, string, struct, tree, tuple, XML, YAML |
| 5 | Infrastructure, deployment, and platforms | AWS, CI/CD, container, deployment, Heroku, Kubernetes, load balancer, Node.js, pipeline, pod, production, staging, Vercel |
| 6 | Systems, subsystems, and architectural components | API gateway, authentication layer, caching layer, client, database layer, message broker, microservice, proxy, rate limiter, REST API, routing layer, server, WebSocket |
| 7 | Mathematical, algorithmic, and scientific terms | Big O notation, binary search, coefficient, complexity, exponent, hash function, iteration, logarithm, matrix, recursion, regex, sorting algorithm, time complexity, traversal |
| 8 | Interface elements and navigation | button, checkbox, dialog, dropdown, footer, header, menu, modal, navigation bar, radio button, scrollbar, sidebar, tab, text field, toggle, tooltip |
| 9 | Numbers, units of measurement, and time | byte, gigabyte (GB), hertz (Hz), hour (h), kilobyte (KB), megabyte (MB), millisecond (ms), minute, nanosecond (ns), second (s), terabyte (TB) |
| 10 | Quoted text (unchangeable text) | `Cannot read properties of undefined`, `ENOENT: no such file or directory`, `Submit` button, `404 Not Found`, `connection refused` |
| 11 | Professional roles, teams, and organizations | administrator, backend developer, contributor, DevOps engineer, frontend developer, Google, maintainer, Microsoft, product owner, QA engineer, reviewer, scrum master, user |
| 12 | Official documents, API references, and standards | API reference, changelog, code of conduct, contributing guide, diagram, figure, Getting Started guide, HTTP specification, note, paragraph, README, release notes, RFC, section, table, warning |
| 13 | Runtime environments and operational conditions | development, environment variable, garbage collection, heap, hot reload, live reload, memory leak, production, sandbox, stack trace, staging, test, thread, timeout, virtual machine |
| 14 | Colors | black, blue, cyan, gray, green, magenta, orange, red, white, yellow |
| 15 | Defects, errors, and fault terminology | assertion failure, bug, crash, deadlock, defect, exception, hang, infinite loop, memory leak, null pointer, race condition, regression, stack overflow, timeout, type error |
| 16 | Computer science, information, and communication technology | AI, algorithm, authentication, authorization, blockchain, containerization, cryptography, database, encoding, encryption, firewall, hashing, internet, machine learning, metadata, neural network, protocol, query, sandbox, schema, token, virtualization |
| 17 | Legal and licensing terms | Apache 2.0, BSD license, compliance, copyright, GPL, license, MIT license, open source, proprietary, terms of service, third-party, trademark, warranty |
| 18 | Database and storage terminology | connection pool, cursor, foreign key, index, migration, NoSQL, ORM, PostgreSQL, primary key, query, Redis, relation, row, schema, seed, SQL, SQLite, stored procedure, table, transaction, view |
| 19 | Network and protocol terminology | DNS, endpoint, HTTP, HTTPS, IP address, localhost, middleware, packet, port, request, response, route, socket, SSH, TCP, TLS, UDP, URL, VPN, WebSocket |

Colors (category 14) are adjectives, but STE-Code classifies them as code-domain
technical nouns. Comparative and superlative color forms (blacker, the reddest)
are not permitted.

The listed terms are examples only. Rule 1.5 does not give a complete list.

### Category selection by documentation type

| Documentation type | Typical categories | Example |
|---|---|---|
| README | 1, 3, 5, 17 | "This package provides a middleware for Express." |
| API documentation | 4, 6, 18, 19 | "The `GET /users/:id` route returns a JSON object with a user struct." |
| Docstrings and comments | 4, 7, 15 | "Traverse the binary search tree in-order and return a sorted array." |
| Commit messages | 1, 15, 18 | "Fix race condition in the connection pool that caused a deadlock on PostgreSQL." |
| Error messages | 9, 13, 15, 19 | "Connection refused: the TCP socket on port 5432 timed out after 30 seconds." |
| Test specifications | 1, 4, 15 | "The test calls `parseConfig` with a null pointer and checks for an assertion failure." |

### Relation to the neighbouring rules

- Rule 1.1 requires approved words for common vocabulary. Rule 1.5 is the
  complement: it permits words outside the dictionary when they name a technical
  concept. Use an approved word whenever one exists.
- Rule 1.6 forbids every unapproved word that Rule 1.5 does not admit. Read the
  two rules as one gate.

### Glossary registration is mandatory

Before you use a code-domain technical noun, add it to the project glossary. Each
entry states: the noun term; its STE-Code category or categories; the approved
meaning in the project context; one correct example sentence. A project without a
glossary drifts into ambiguity and breaks Rule 1.11 (one term per concept).

### Paradigm notes

| Paradigm | Lean on categories | Correct | Incorrect |
|---|---|---|---|
| Object-oriented (Java, C++, C#, Python) | 1, 4, 6, 16 | "The `UserRepository` class extends the `BaseRepository` abstract class and implements the `IAuditable` interface." | "The repo leverages the base to retrieve user data." (use "use"; use "repository") |
| Functional (Haskell, Elixir, Clojure, Rust) | 4, 7, 16 | "The function returns an `Option` monad. Use pattern matching to extract the value." | "The combinator stuff chains stuff together." (name the terms: parser combinator, function, pipeline) |
| Procedural (C, Go, Bash) | 4, 13, 19 | "The Go goroutine reads from the channel. The mutex prevents a race condition." | "The script fires off a subprocess to crunch the numbers." (use "starts", "process") |
| Declarative (SQL, Terraform, Kubernetes) | 5, 10, 12, 18 | "The `SELECT` statement uses an `INNER JOIN` on the `users` and `orders` tables." | "K8s spins up a bunch of pods inside the thing." (use "Kubernetes", "starts", "namespace") |
| Systems (Rust ownership, C memory) | 4, 13, 15, 16 | "The borrow checker prevents dangling pointers at compile time." | "Rust's thingy stops you from shooting yourself in the foot." (idiom forbidden by P10) |

```java
/**
 * The UserRepository class extends the BaseRepository abstract class
 * and implements the IAuditable interface.
 * Use the findById method to get a user struct from the database layer.
 */
public class UserRepository extends BaseRepository implements IAuditable {
    public User findById(Long id) { /* ... */ }
}
```

```rust
// The Rust compiler enforces the ownership rules.
// The borrow checker prevents dangling pointers at compile time.
fn parse_input(buffer: Vec<u8>) -> Result<String, Utf8Error> {
    let text = String::from_utf8(buffer)?;  // heap allocation (category 13)
    Ok(text)
}
```

### Edge cases

1. **Framework names that are also common words** (React, Vue, Swift, Go, Rust,
   Elm, Next, Nest). The framework name is a technical noun (category 3 or 5) and
   does not follow the dictionary meaning. Capitalize it, or use the full term
   ("the Swift language", "the Rust compiler"), so it cannot be read as the
   approved verb.
2. **Code keywords in documentation** (`if`, `for`, `return`, `class`, `async`).
   Inside backticks they are quoted text (category 10) and exempt. In prose they
   must follow the approved meaning. Write "If the request fails, return
   `500 Internal Server Error`." — not a bare `500`.
3. **Abbreviations and acronyms** (API, JSON, SQL, HTML, HTTP, TCP, DNS, URL) are
   technical nouns in categories 16, 18, or 19. Expand each at first use unless
   the audience universally knows it: "the application programming interface
   (API) uses Hypertext Transfer Protocol Secure (HTTPS)".
4. **Generated code and generated documentation** (OpenAPI specs, protobuf stubs,
   migration files, JSDoc or Sphinx output) are exempt, because a machine
   produces them. Every human-written comment or annotation inside them is not.
5. **Project-specific internal names** (`PhoenixCache`, "Hammerhead subsystem")
   are technical nouns under category 1 or 6 **only when registered in the
   project glossary**. Without registration they are unapproved words and break
   Rule 1.6.
6. **Numbers as technical nouns.** Fixed named values — version numbers
   (`Node.js 18`), status codes (`404`), port numbers (`port 5432`) — are
   category 9 nouns or quoted text and must appear verbatim. Do not write "the
   default db port" or "a not found error".

### Grammar of technical nouns

- **Articles.** Same as approved nouns: "the" for a specific instance, "a"/"an"
  for an indefinite one, no article for plural general reference — "Kubernetes
  pods run in a namespace."
- **As modifiers.** A technical noun may modify another to form a compound; both
  parts must belong to a recognized category. "The Redis cache server stores the
  session data." Not: "The thing layer processes the stuff queue."
- **Possessive.** Permitted only for category 11 (roles, organizations):
  "the user's session data". Use an "of" construction elsewhere: "the
  configuration of the Docker container" — not "the Docker container's
  configuration".
- **Plurals.** Standard English rules; acronyms add a lowercase "s" with no
  apostrophe. "two APIs and three SQL queries" — not "two API's".
- **Capitalization.** Proper-noun technical nouns keep published casing
  (`TypeScript`); common ones stay lowercase unless sentence-initial
  (controller, endpoint, middleware).

### Worked pair

> **Non-STE:** The developer used the thing to get data from the storage layer and put it on the screen.
>
> **STE:** The frontend developer used the API client to get data from the database and show it on the UI.

frontend developer (11), API client (16), database (18), UI (8). "Thing" names
nothing; "screen" is category 2 hardware, not the interface element.

> **Non-STE:** The endpoint leverages the middleware to authenticate the request and then kicks off a background job to crunch the data.
>
> **STE:** The endpoint uses the authentication middleware to check the request. The endpoint then starts a background job to process the data.

> **Non-STE:** First, snag the repo and then cd into it. After that, fire up the dev server.
>
> **STE:** First, clone the repository. Then, change to the repository directory. After that, start the development server.

> **Non-STE:** Bumped deps and fixed the wonky timeout thing that was breaking prod.
>
> **STE:** Update dependencies. Fix a timeout defect in the connection pool that caused a crash in production.

### Rule 1.5 cross-references

Rule 1.1 (approved words) · Rule 1.2 (part of speech) · Rule 1.3 (approved
meanings) · Rule 1.4 (verb and adjective forms) · Rule 1.6 (unapproved words) ·
Rule 1.7 (nouns not as verbs) · Rule 1.8 (standard names) · Rule 1.9 (short
names) · Rule 1.11 (one term per concept) · Rule 1.12 (technical verbs).

---

## Rule 1.6 — Use an unapproved word only when it is a code-domain technical noun, or part of one

**Rule.** Use a word that is not approved in the controlled terminology only when
it is a code-domain technical noun or part of a code-domain technical noun.

Some words are listed as unapproved. If such a word fits an applicable technical
noun category, it may be used in that noun sense — and only in that sense.

### The three-test gate

An unapproved word may stay only if it clears all three tests.

| Test | Question | Fails | Passes |
|---|---|---|---|
| 1 | Is the word unapproved? | "function" (approved — Rule 1.1 handles it) | "handler" enters the gate |
| 2 | Is it a technical noun, or inside a compound technical noun (Rule 1.5)? | "handler" alone; "main" alone | "event handler" (cat. 1); "main branch" (cat. 5) |
| 3 | Is it used as a noun in the sentence? | "This class handlers the request." | "The event handler processes the request." |

Failing any test means: replace with the approved alternative, or restructure.

### Compound checklist

A compound counts as a code-domain technical noun only when all three hold:

1. The words together name one concept that the domain recognizes.
2. The compound fits one of the nineteen categories.
3. Swapping the unapproved word for its approved alternative changes the
   recognized name and causes confusion.

Swap test: if the approved alternative still names the same concept, it is not a
technical noun — make the replacement. If the swap produces a name nobody in the
domain would recognize, the compound is a technical noun and the unapproved word
stays inside it.

Authority for "recognized": the project glossary, the framework or language
documentation, or an industry standard (RFC, W3C, POSIX).

### Core pairs

> **Non-STE:** The handler processes each incoming event.
>
> **STE:** The function processes each incoming event.
>
> **STE:** The event handler processes each incoming event. *("Event handler" is category 1.)*

> **Non-STE:** The main configuration has the latest values.
>
> **STE:** The primary configuration has the latest values.
>
> **STE:** Merge the feature branch into the main branch. *("Main branch" is the Git term, category 5; "primary branch" is not.)*

> **Non-STE:** Make sure that the two connectors at the base of the chassis engage.
>
> **STE:** Make sure that the two connectors at the bottom of the chassis engage.
>
> "Base" stays inside "base case" (cat. 7), "base class" (cat. 1), "base URL" (cat. 8).

### Descriptive adjective or technical noun?

| Permitted (technical noun) | Replace (descriptive) |
|---|---|
| "Check out the main branch before you merge." | "The main configuration has the latest values." → primary |
| "The base case returns the single-element array." | "The base configuration is loaded first." → primary |
| "The event handler processes each request." | "The handler processes each request." → function |

Criterion: does the compound appear in the official documentation of the
framework, language, or standard? If yes, technical noun. If no, prose — replace.

### Category overlap

The same unapproved word can pass in different categories when its meaning
changes: "base" in "base case" (7), "base class" (1), "base URL" (8); "cache" in
"cache layer" (6), "cache invalidation" (16), "query cache" (18). Each names a
specific concept — not a general adjective or verb.

### Worked trace

> **Non-STE:** The main config loader backups the data through the handler pipeline.
>
> **STE:** The primary config loader makes an auxiliary copy of the data through the processing pipeline.

| Word / phrase | Unapproved? | Technical noun? | Used as noun? | Result |
|---|---|---|---|---|
| main config loader | yes | "main" is a general adjective here | — | "main" → "primary" |
| backups | yes | verb sense is not a technical noun | no, verb | → "makes an auxiliary copy" |
| handler pipeline | yes | not a recognized compound | yes, but fails Test 2 | → "processing pipeline" |

### Applied by documentation type

**README.**

> **Non-STE:** The base setup leverages Express for the main API and MongoDB for the database backend. The handler backs up the data every night.
>
> **STE:** The primary setup uses Express for the main API and MongoDB for the database backend. The function makes an auxiliary copy of the data each night.

Package names (`Express`, `MongoDB`, `react-router`) are technical nouns
(cat. 3, 18). Keep a package-name compound whole — never split the unapproved
word out of `react-router`.

**API documentation.** Paths and field names stay; verbs must be approved.

```yaml
/api/v1/backup:
  summary: Makes an auxiliary copy of the database. Returns a backup ID.
  responses:
    '200':
      description: The auxiliary copy was made. The event handler processed the request.
```

**Docstrings and comments.**

```python
def serve(req):
    """Processes the request and returns a response."""
    # base case: the event handler returns null when req is empty
    if not req:
        return None
    return build(req)
```

"Handles" → "processes"; "base case" stays (cat. 7); "handler" → "event handler".
In Go: "the base URL is null and the event handler runs longer than the timeout"
— not "times out".

**Commit messages.** Conventional prefixes are technical nouns; the description
obeys the gate.

```
feat: add an event handler for the auxiliary-copy endpoint and the primary config loader
fix: run the backup script before the primary migration
chore: update the main config loader settings   # glossary names the file "main config"
```

**Error messages.**

```
Error: primary config file not found. The event handler for auxiliary copies will stop.
Build failed: the primary config loader ran longer than the timeout. The auxiliary-copy handler did not start.
```

### Paradigm notes

- **Object-oriented.** Class and pattern names stay: `BaseService`, `MainFactory`.
  Verbs must be approved: "handlers" → "processes", "backups" → "makes auxiliary
  copies", "factories" → "makes". A pattern name is never a verb: "This class
  uses the Singleton pattern for the connection used by all callers."
- **Functional.** Type and monad names stay (`ReaderT`). Use "base monad" only if
  the library's own docs use it; otherwise "underlying monad". "Base case" is a
  permitted compound (cat. 7).
- **Procedural.** `main` as the entry-point function name and the Go `main`
  package are technical nouns and stay; "main goroutine" as a general adjective
  becomes "primary goroutine". Make a bare "handler" explicit: "file handler".
- **Declarative.** Table names (`backup_logs`) and resource kinds (`ConfigMap`,
  `Deployment`) stay; "backups" → "keeps auxiliary copies"; "base settings" →
  "primary settings".
- **Systems.** `unsafe` block, `raw pointer`, `dangling pointer` are technical
  nouns. As a descriptive adjective, "unsafe" is not approved: write "This
  approach is not safe because the buffer is shared." "Base allocation" →
  "primary allocation"; bare "handler" → "drop handler".

### Rule 1.6 edge cases

1. **Framework name that is also an unapproved word.** `pandas`, `Express`,
   `webpack` are technical nouns when they name the tool, with published
   capitalization. As general verbs they are unapproved: "use pandas to load the
   CSV into a data frame, then use Express to send the results as JSON".
2. **Code keyword that is also a general word.** Inside backticks it is quoted
   text (cat. 10). In prose its role decides: "The category of objects that
   `return` a value must not block the primary thread." ("class" as a general
   noun → "category"; "main" → "primary".)
3. **A compound that looks technical but is not recognized.** "The handler
   pipeline integrates with the backup orchestrator via the main dispatcher"
   contains three invented compounds → "The processing pipeline integrates with
   the auxiliary-copy service through the primary dispatcher."
4. **Auto-generated documentation.** Apply the gate to the source docstring or
   annotation, not the generated output: `/// <summary>Processes the
   auxiliary-copy operation for the primary controller.</summary>`
5. **Project and brand names.** `Homebrew` stays (cat. 3 or 11); the descriptive
   prose around it is still reviewed: "Use Homebrew to install the primary
   packages. Then use `webpack` to make the primary bundle."

### Terminology referenced by Rule 1.6

| Term | Status | Approved alternative | Permitted inside |
|---|---|---|---|
| BASE (n) | unapproved | BOTTOM (n) for a surface or stack position; ROOT (n) for a filesystem root | base case (7), base class (1), base URL (8) |
| MAIN (adj) | unapproved | PRIMARY (adj) | main branch (5), main function / `main()` (1) |
| HANDLER (n) | unapproved | FUNCTION (n) | event handler, request handler, file handler (1) |
| BACKUP (n, v) | unapproved | AUXILIARY (adj); "makes an auxiliary copy" for the verb | backup file, `backup_logs` (18), `/api/v1/backup` (19) |
| BOTTOM (n, adj) | approved | — | — |
| FUNCTION (n) | approved | — | — |
| PRIMARY (adj) | approved | — | — |
| AUXILIARY (adj) | approved | — | — |
| ROOT (n) | technical noun | top-level directory (5 or 13) | — |

Categories most used by this rule: 1 (event handler, base class, main function),
3 (Express, pandas, webpack), 5 (main branch, ConfigMap), 7 (base case), 8 (base
URL, Git root), 18 (backup file, config file), 19 (backup as a resource name).

### Rule 1.6 cross-references

Rule 1.1 · Rule 1.2 · Rule 1.5 · Rule 1.7 · Rule 1.8 · Rule 1.9 · Rule 1.11 ·
Rule 1.12.

---

---

<!-- rules-sec2.md -->

# Level 3 — Section 2: Technical Noun Rules (2.1–2.3)

Distilled reference for LLMs that generate code documentation. These three
rules govern how to write multi-word technical nouns so they stay short, clear,
and parseable. All examples are code-domain. Adapted from ASD-STE100 Issue 9.

Scope of this slice:
- Rule 2.1 — Keep Technical Nouns Short
- Rule 2.2 — Write Long Technical Nouns in Full
- Rule 2.3 — Use Hyphens Between Words Used as One Unit

Core idea shared by all three: a technical noun phrase (a class name, config
key, endpoint path, error type, test fixture, or commit subject) should stay
short — ideally three words or fewer. When it must be longer, write it in full
once, then use a short form or abbreviation. Use prepositions (`of`, `on`,
`in`, `for`, `to`) to break ownership chains, and hyphens only to glue related
words into one unit.

## Rule 2.1 — Keep Technical Nouns Short

**Source:** ASD-STE100 Issue 9, Rule 2.1 (adapted for code documentation).

### Rule
To keep multi-word technical nouns short, use prepositions (`of`, `on`, `in`,
`for`) and explain the noun instead of stacking modifiers. A code component that
is a technical noun — a module name, class name, config key, endpoint path,
error type, or test fixture — must stay short so the reader parses it without
effort.

Split a noun chain at its ownership/containment points and connect the parts
with prepositions. Do not write one long noun that stacks modifiers.

### Why it matters
- A reader scans docs fast. A stacked noun such as
  `authentication_token_expiration_refresh_interval_setting` hides which part
  owns which. Prepositions reveal the tree.
- Short technical nouns match how code is already structured: a config key,
  class, or JSON field is one short concept; prepositions show how concepts
  relate.
- Use short plain words (Microsoft/Google style): `use` not `utilize`/`leverage`
  /`employ`; `start`/`stop` not `commence`/`initiate`/`terminate`.
- Approved code-domain adjectives stay attached to the short noun they modify:
  `idempotent`, `immutable`, `thread-safe`, `atomic`, `nullable`, `deprecated`,
  `stateless`, `backward-compatible`, `asynchronous`, `concurrent`,
  `deterministic`. Write `the idempotent retry policy`, not `idempotentretrypolicy`.

### How to apply
1. Find a noun that stacks two or more modifiers (a "noun chain").
2. Split the chain at ownership/containment points.
3. Connect parts with `of`, `on`, `in`, or `for`.
4. Name each code component by its short technical noun (class, key, file),
   not a merged word.
5. In instruction text use approved verbs: `set`, `get`, `make`, `show`,
   `check`, `remove`, `send`, `start`, `stop`, `use`, `update`. Do not use
   `configure` for `set`, `retrieve` for `get`, `delete`/`purge` for `remove`,
   or `display` for `show`.

### Examples in STE-Code

**1. Configuration key — auth token refresh**
- Non-STE: Authentication token expiration refresh interval setting
- STE: Setting of the refresh interval of the expiration of the authentication token

```yaml
# STE-Code: short keys, one concept per level
auth:
  token:
    expiration:
      refresh_interval_seconds: 300   # setting of the refresh interval of the expiration of the authentication token

# Non-STE: one long key hides the relationship (do not write this)
authentication_token_expiration_refresh_interval_setting: 300
```

```python
def get_refresh_interval(token):
    """Return the setting of the refresh interval of the expiration of the authentication token."""
    return token.expiration.refresh_interval_seconds
```

**2. Deployment labels — middleware config**
- Non-STE: Install the forward service request validator middleware config tags.
- STE: Install the config tags on the validator middleware of the request of the forward service.

```bash
# the tag goes on the validator middleware of the request of the forward service
kubectl label pods -l app=forward-service middleware=validator config=enabled
```

```yaml
# Non-STE (do not write this)
install_forward_service_request_validator_middleware_config_tags: true
```

**3. Cleanup task — migration lock files**
- Non-STE: Remove the database migration script output directory lock files.
- STE: Remove the lock files that lock the output directory of the migration script of the database.

```python
def remove_migration_lock_files(db_name: str) -> int:
    """Remove the lock files that lock the output directory of the migration script of the database."""
    output_dir = Path("migrations") / db_name / "output"
    removed = 0
    for lock in output_dir.glob("*.lock"):
        lock.unlink()
        removed += 1
    return removed
```

```python
def test_remove_migration_lock_files(tmp_path):
    out = tmp_path / "app" / "output"
    out.mkdir(parents=True)
    (out / "write.lock").write_text("")
    count = remove_migration_lock_files("app")
    assert count == 1
    assert not any(out.glob("*.lock"))
```

**4. Test setup — cache hook alignment**
- Non-STE: Adjust to obtain cache invalidation hook alignment with the event emitter.
- STE: Adjust the cache invalidation hook until it aligns with the event emitter.

```python
def align_cache_hook(hook, emitter, timeout: float = 5.0) -> bool:
    """Adjust the cache invalidation hook until it aligns with the event emitter."""
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        if hook.target is emitter:
            return True
        hook.nudge()
    return False
```

**5. API documentation — retry policy**
- Non-STE: Payment gateway timeout retry exhaustion notification handler.
- STE: Handler of the notification of the exhaustion of the retry of the timeout of the payment gateway.

```python
class PaymentGatewayTimeoutRetryExhaustionNotificationHandler:
    """Handler of the notification of the exhaustion of the retry of the timeout of the payment gateway."""

    def handle(self, notice) -> None:
        log.error("retry of the timeout of the payment gateway is exhausted")
```

**6. Commit message — schema change**
- Non-STE: User account profile avatar image storage bucket policy update.
- STE: Update of the policy of the storage bucket of the image of the avatar of the profile of the user account.

```text
# STE-Code commit title
Update the policy of the storage bucket of the image of the avatar of the profile of the user account

# Non-STE commit title (do not write this)
useraccountprofileavatarimagestoragebucketpolicyupdate
```

**7. README section — rate limit**
- Non-STE: The inbound request rate limit window reset schedule controls the burst.
- STE: The schedule of the reset of the window of the rate limit of the inbound request controls the burst.

```markdown
The schedule of the reset of the window of the rate limit of the inbound
request controls the burst. Set the window to 60 seconds.
```

**8. Code comment — background job**
- Non-STE: The background worker queue overflow alert suppression rule runs on the staging cluster.
- STE: The alert suppression rule on the overflow of the background worker queue runs on the staging cluster.

```python
def install_alert_rule(cluster: str) -> None:
    rule = AlertSuppressionRule(on=OverflowOf(WorkerQueue(background=True)))
    deploy(rule, cluster="staging")
```

### See also
- Rule 1.5 — Technical Noun Categories (what counts as a technical noun).
- Rule 1.3 — Use Approved Words Only (keep verbs/nouns plain).
- Rule 2.2 — Write Long Technical Nouns in Full.
- Rule 2.3 — Use Hyphens Between Words Used as One Unit.

## Rule 2.2 — Write Long Technical Nouns in Full

**Source:** ASD-STE100 Issue 9, Rule 2.2 (adapted for code documentation).

### Rule
When a technical code noun has more than three words, write it in full the
first time it occurs. Then use one of these methods to make it clear:
- Give a shorter form of the technical code noun.
- Use hyphens (`-`) between words used as one unit (see Rule 2.3).
- Use prepositions (`of`, `on`, `in`, `for`, `to`) to split a long noun into
  short, separate parts (see Rule 2.1).

A long multi-word code noun can be one long technical noun, or a combination of
shorter ones. When the noun is an official term your company, framework, or
subject field uses, you must write it in its approved form — even if you cannot
split it.

### Method 1 — Shorter form / abbreviation
If a long technical code noun comes from an official code document (API spec,
schema, OpenAPI file, architecture diagram), write it in full the first time it
occurs. Then, if possible, give a shorter form or approved abbreviation in
parentheses, and reuse that form in the rest of the document.

- Write "user session cache invalidation lock handler" in full, then refer to
  it as the "invalidation lock handler" (3 words, obeys Rule 2.1).
- Approved abbreviations from official code docs are allowed, but a text full
  of abbreviations is hard to read. If an approved noun is three words or less,
  do not abbreviate.

```python
def initialize_session_lock(user_id: str) -> None:
    """Initialize the user session cache invalidation lock handler.

    The invalidation lock handler locks the cache of the user session so that
    a background job cannot read stale data while a write is in flight.
    """
    handler = UserSessionCacheInvalidationLockHandler(user_id)
    handler.engage()   # from here, refer to it as the "invalidation lock handler"
```

Abbreviation defined on first use, then reused:

```typescript
// The Main Form Validation Module (MFVM) is a TypeScript module that
// includes a Main Export Controller Unit (MECU) and a Data Bridge (DB).
interface FormPayload { fields: Record<string, unknown>; }

class MainFormValidationModule {       // MFVM
  constructor(
    private readonly exportController: MainExportControllerUnit,  // MECU
    private readonly bridge: DataBridge,                          // DB
    private readonly config: DynamicConfigUnit,                   // DECU
  ) {}

  submit(payload: FormPayload): void {
    this.config.onEvent("submit", () => this.exportController.run(payload));
  }
}
```

Parts list — name each part in full; do not pack parts into letter codes:

```yaml
controller:
  data_transformer_assembly:   # (8)  part of the view body
  pipeline_validator_assembly: # (15) sits on its seat
  buffer_assembly:             # (17) part of the view body

# Non-STE (do not write this):
#   parts: [DTA_8, PVA_15, BA_17, VB_20]
```

```python
def disassemble_controller(view_body, validator_seat):
    view_body.remove(data_transformer_assembly)        # (8)
    validator_seat.remove(pipeline_validator_assembly) # (15)
    view_body.remove(buffer_assembly)                  # (17)
```

### Method 2 — Prepositions to break a long noun
When a long noun is a chain of short nouns (e.g. "user authentication token
refresh failure retry policy"), make the main noun the head of the sentence and
attach the rest with prepositions. Put the key noun first, then add modifiers
with `of`, `on`, `in`, `for`, `to`.

- Non-STE: Configure the user authentication token refresh failure retry policy before you deploy the service to production.
- STE: Configure the retry policy for the failure of the refresh of the user authentication token before you deploy the service to production.

- Non-STE: Install the background worker queue overflow alert suppression rule on the staging cluster.
- STE: Install the alert suppression rule on the overflow of the background worker queue on the staging cluster.

- Non-STE: Remove the database connection pool exhaustion recovery timeout configuration parameter from the settings file.
- STE: Remove the configuration parameter that sets the recovery timeout for the exhaustion of the database connection pool from the settings file.

```python
def set_recovery_timeout(pool, seconds: float) -> None:
    """Set the configuration parameter that sets the recovery timeout
    for the exhaustion of the database connection pool."""
    pool.config["recovery_timeout_seconds"] = seconds
```

- Non-STE: Update the build script to obtain output directory naming consistency with the package convention.
- STE: Update the build script until the output directory naming is consistent with the package convention.

### Method 3 — Hyphenate words used as one unit
When two or more words act as a single modifier before a noun, use a hyphen to
show they are one unit. Hyphenate compound modifiers such as `request-response`,
`read-write`, `build-time`, `out-of-band`, `end-to-end`, `run-time`. Do NOT
hyphenate when the first word is an `-ly` adverb (e.g. "a publicly documented
API" stays open).

- Non-STE: Set the request response mapping handler to the new schema before the migration.
- STE: Set the request-response mapping handler to the new schema before the migration.

- Non-STE: Run the build time configuration check after you compile the module.
- STE: Run the build-time configuration check after you compile the module.

- Non-STE: Add an end to end test for the payment flow before you merge the change.
- STE: Add an end-to-end test for the payment flow before you merge the change.

- Non-STE: Use the out of band signal to stop the long running job.
- STE: Use the out-of-band signal to stop the long-running job.

```python
def handle_request_response(handler: "RequestResponseMappingHandler") -> None:
    """Set the request-response mapping handler to the new schema."""
    handler.apply(schema=SCHEMA_V2)

def run_build_time_check() -> None:
    """Run the build-time configuration check after you compile the module."""
    ...
```

Note: hyphenation groups words into one unit but does not make a long technical
noun short. If the hyphenated unit still has more than three words (e.g.
"request-response mapping handler"), write it in full the first time, then use
the shorter form ("mapping handler") afterward.

### Expanded code-domain example pairs
Each Non-STE line breaks the rule; each STE line writes the long noun in full,
then uses the shorter form or abbreviation.

- Non-STE: The USCIlh must run before the shutdown hook releases the cache. If the USCIlh fails, the stale session remains.
- STE: Initialize the user session cache invalidation lock handler (the handler that locks the cache of the user session; in this procedure, we call it the "invalidation lock handler"). Run the invalidation lock handler before the shutdown hook releases the cache. If the invalidation lock handler fails, the stale session remains.

```python
class UserSessionCacheInvalidationLockHandler:
    def engage(self) -> None: ...
    def release(self) -> None: ...

def shutdown_hook(session_id: str) -> None:
    handler = UserSessionCacheInvalidationLockHandler(session_id)
    handler.engage()          # invalidation lock handler
    if not handler.release():
        raise StaleSessionError(session_id)  # stale session remains
```

- Non-STE: The MFVM uses the MECU and the DB. The DECU sends events to the MFVM so that the MFVM can get data from the MFP.
- STE: The Main Form Validation Module (MFVM) is a TypeScript module that includes a Main Export Controller Unit (MECU) and a Data Bridge (DB). The Dynamic Config Unit (DECU) sends events to operate the MFVM, and the MFVM gets form data from the Main Form Provider (MFP).

```typescript
const mfvm = new MainFormValidationModule(     // MFVM
  mecu,  // Main Export Controller Unit
  db,    // Data Bridge
  decu,  // Dynamic Config Unit
);
decu.onEvent("submit", () => mfvm.submit(mfp.getData()));  // MFP = Main Form Provider
```

- Non-STE: Call the DTA to configure the MFVM before you run the build, then check the MFVM output for errors.
- STE: Use the data transformer adapter to configure the main form validation module before you run the build. Then check the output of the main form validation module for errors.

```bash
make configure MODULE=data-transformer-adapter   # data transformer adapter
make build MODULE=main-form-validation-module    # main form validation module
make test   MODULE=main-form-validation-module && echo "output checked for errors"
```

- Non-STE: Update the cross service request tracing correlation identifier generator after the schema change.
- STE: Update the correlation identifier generator for the tracing of the request across services after the schema change. (On first use, write "cross-service request tracing correlation identifier generator" in full, then refer to it as the "correlation identifier generator.")

```python
def update_correlation_generator(schema: dict) -> None:
    """Update the cross-service request tracing correlation identifier generator.

    After the first use, this component is the correlation identifier generator.
    """
    CorrelationIdentifierGenerator.for_request_tracing().apply(schema)
```

- Non-STE: The CI pipeline docker image layer cache warming step now runs in parallel.
- STE: The cache warming step for the layer of the Docker image of the CI pipeline now runs in parallel. (On first use, write "CI pipeline Docker image layer cache warming step" in full, then refer to it as the "cache warming step.")

```yaml
jobs:
  warm_cache:   # cache warming step for the layer of the Docker image of the CI pipeline
    runs-on: ubuntu-latest
    strategy:
      matrix:
        layer: [base, deps, build]
    steps:
      - run: ./scripts/warm-cache.sh "${{ matrix.layer }}"
```

- Non-STE: Document the legacy database migration rollback failure notification webhook endpoint in the runbook.
- STE: Document the webhook endpoint for the notification of the failure of the rollback of the legacy database migration in the runbook. (On first use, write "legacy database migration rollback failure notification webhook endpoint" in full, then refer to it as the "notification webhook endpoint.")

```text
Document the webhook endpoint for the notification of the failure of the
rollback of the legacy database migration. After the first use, refer to it
as the "notification webhook endpoint" and add it to the on-call alert route.
```

### How to apply in code documentation
1. Find the long technical code noun (more than three words) in your sentence.
2. Write it in full the first time it occurs. If it comes from an official
   source (API spec, schema, architecture diagram), keep the exact approved form.
3. Give a shorter form or approved abbreviation right after the full form, in parentheses.
4. In the rest of the document, use only the shorter form or the abbreviation.
5. If the noun is a chain of short nouns, split it with prepositions (Rule 2.1).
6. If two or more words act as one modifier, hyphenate them (Rule 2.3).
7. Do not fill a procedure with abbreviations. A short, clear noun beats a
   string of letters.

> Microsoft/Google style note: use short plain words — `use` not
> `utilize`/`leverage`/`employ`; `start`/`stop` not `commence`/`initiate`/`terminate`.

### See also
- Rule 2.1 — Keep Technical Nouns Short.
- Rule 1.5 — Technical Noun Categories and Your Company Glossary.
- Rule 1.3 — Use Approved Words (use, set, get, make, show, check, remove, send, start, stop).

## Rule 2.3 — Use Hyphens Between Words Used as One Unit

**Source:** ASD-STE100 Issue 9, Rule 2.3 (adapted for code documentation).

### Rule
A hyphen connects words or parts of words. Use hyphens between words to show
how related words operate as one unit. This keeps multi-word code nouns within
the three-word limit of Rule 2.1. A hyphenated word counts as one word, so it
fills only one of the three slots a noun phrase may use.

- Do NOT connect unrelated words with a hyphen — it changes the meaning of the
  multi-word noun. If unsure, explain the noun plainly, then use a shorter form
  or an approved abbreviation.
- If an approved technical code noun already includes hyphens — e.g.
  `input-output stream`, `thread-safe queue`, `backward-compatible API` — keep
  the hyphen. Do not change official terms.
- Do NOT use hyphens to make groups of more than three words. Keep the hyphen
  group to at most three words; split longer chains with prepositions
  (`of`, `on`, `in`).

### Examples in STE-Code

| Example | Note |
|---|---|
| Make sure that the fail-safe shutdown-handler connection is safe. | (3 words: make / sure / connection) |
| Inspection of the request rate-limit device. | (3 words: inspection / of / device) |
| The thread-safe queue keeps the order of the write operations. | (3 words: queue / keeps / order) |
| Remove the backward-compatible API client before you make the change. | (3 words) |

When a hyphen joins two related words, the pair is one unit. Apply this in
procedural and descriptive code docs so the reader parses the noun without
re-reading.

**Full example — hyphenate related words, keep to three words**
- Non-STE: Move the `main-feature-flag-rollback-handler` trigger to start the test run. (2 words, but not correct — four words joined as one unit)
- STE: Move the `main-feature-flag` rollback-handler trigger to start the test run. (3 words: move / trigger / run)

```bash
# the hyphen joins the related pair only
make test trigger=rollback-handler flag=main-feature-flag
```

```python
def move_trigger(main_feature_flag: str, rollback_handler: str) -> None:
    """Move the main-feature-flag rollback-handler trigger to start the test run."""
    trigger = f"{main_feature_flag}:{rollback_handler}"
    start_test_run(trigger)
```

**Full example — do not hyphenate a three-word approved technical noun**
When the official name is three words or less, leave the spaces. Hyphenating it
changes the count and confuses the reader.
- Non-STE: A. Remove the `data-adapter` assembly (8) from the view body (20). B. Remove the `pipeline-validator` assembly (15) from its seat.
- STE: A. Remove the `data adapter` assembly (8) from the view body (20). B. Remove the `pipeline validator` assembly (15) from its seat.

```python
def remove_assembly(name: str, part_id: int) -> None:
    """Remove the data adapter assembly (part_id) from the view body."""
    detach(name, part_id)
    log(f"removed {name} assembly {part_id}")

remove_assembly("data adapter", 8)
remove_assembly("pipeline validator", 15)
```

**Full example — keep a hyphen the official name already has**
If official code docs or an approved standard already hyphenates a term, keep
the hyphen. Removing it changes the term.
- Non-STE: The `input output stream` is part of the logging system.
- STE: The `input-output stream` is part of the logging system.

```python
class LoggingSystem:
    def __init__(self, stream: "InputOutputStream") -> None:
        # The input-output stream is part of the logging system.
        self.stream = stream

    def write(self, message: str) -> None:
        self.stream.push(message)
```

```yaml
logging:
  # The input-output stream is part of the logging system.
  input-output-stream:
    buffer-size: 4096
    flush-on-error: true
```

### See also
- Rule 2.1 — Keep Technical Nouns Short (the three-word limit hyphenated units help you meet).
- Rule 1.5 — Use Technical Nouns from the Approved Categories (where hyphenated code terms such as `thread-safe queue` and `backward-compatible API` are defined).
- Rule 2.2 — Write Long Technical Nouns in Full (pair hyphenated nouns with short approved verbs such as `make`, `get`, `set`, `start`, `remove`).

<!-- END-SEC2-4 -->

---

<!-- rules-sec3.md -->

# Level 3 — Section 3: Verbs

Scope: STE-Code Section 3, Rules 3.1 through 3.7. These rules control which verb
forms you can use, which tenses are approved, how to use the past participle,
how to avoid auxiliary constructions and "-ing" verbs, when to use the active
voice, and when to use a verb instead of a noun.

Audience: an LLM that writes or edits code documentation (README files, API
reference, docstrings, code comments, commit messages, error messages, CLI help,
configuration comments).

## Section 3 at a glance

| Rule | Statement | Primary test |
|---|---|---|
| 3.1 | Use only the verb forms that the dictionary gives. | Is the form one of the four listed lines of the entry? |
| 3.2 | Use only the approved verb forms and tenses. | Is the tense infinitive, imperative, simple present, simple past, simple future, or past participle as an adjective? |
| 3.3 | Use the past participle form as an adjective. | Does the word give a condition, before a noun or after be/become/stay? |
| 3.4 | Do not use auxiliary verbs to make complex verb constructions. | Does the sentence stack have/be/will/can/must + past participle? |
| 3.5 | Use the "-ing" form only as a technical noun or as a modifier in a technical noun. | Is the "-ing" word acting as a verb? Then it is not approved. |
| 3.6 | Use the active voice. | Ask "by whom or by what?" If the sentence answers it, the sentence is passive. |
| 3.7 | Use an approved verb to describe an action, not a noun. | Is the action hidden in a noun phrase such as "gives an indication of"? |

## Quick decision procedure

1. Find the verb in the STE-Code dictionary. If the verb is not there, replace it
   with the approved verb (Rule 3.1, Rule 3.7).
2. Choose one of the six approved forms (Rule 3.2).
3. Name the actor and put the actor in the subject position (Rule 3.6).
4. Remove every auxiliary chain (Rule 3.4).
5. Remove every "-ing" verb. Keep "-ing" only inside a technical noun (Rule 3.5).
6. Keep the past participle only as an adjective (Rule 3.3).
7. If a sentence becomes long, split it into two short sentences and join the
   sequence with "Then".

---

## Rule 3.1 — Use only the verb forms that the dictionary gives

The STE-Code dictionary gives the allowed forms of each approved verb. Use only
those forms. Do not use gerunds, participles with auxiliaries, or inflected forms
that the entry does not list.

Each entry shows four forms in this order: base form, third-person singular,
simple past, past participle.

```
VALIDATE (v)
VALIDATES
VALIDATED,
VALIDATED

WRITE (v)
WRITES
WROTE,
WRITTEN
```

### How to read a dictionary entry

| Line | Form | Example with WRITE | Where you use it |
|---|---|---|---|
| 1 | Base form (infinitive and imperative) | WRITE | "Write the log." / "to write the log" |
| 2 | Third-person singular, simple present | WRITES | "The logger writes the record." |
| 3 | Simple past | WROTE | "The job wrote the record." |
| 4 | Past participle (as an adjective) | WRITTEN | "the written log" |

If a form is not on one of those four lines, the form is not approved. The simple
future is not a separate line: you make it with "will" and the base form
("will write").

### The four approved verb categories

| Category | Verbs |
|---|---|
| Development operations | build, compile, test, lint, format, commit, push, deploy, rollback |
| Data operations | read, write, serialize, deserialize, parse, encode, decode, query, insert, migrate |
| Application operations | handle, route, authenticate, authorize, validate, schedule, dispatch, resolve |
| Communication operations | send, receive, publish, subscribe, stream, poll, broadcast, connect |

### How to apply the rule

1. Find the verb in the STE-Code dictionary.
2. If the verb is not in the dictionary, use the approved verb instead.
3. If the verb is in the dictionary, use one of the four listed forms only.
4. Do not make a new form from an approved verb. "Parsing", "parseable", and
   "parser" are not verb forms of PARSE. A noun such as "parser" is approved only
   when the dictionary or a technical noun category gives it.
5. Use the past participle only as an adjective ("the parsed manifest", "the
   deprecated method"). Do not use it with "have", "has", "had", or "get".

### Frequent replacements

| Do not use | Use |
|---|---|
| generate | make |
| retrieve | get |
| verify | check |
| utilize, leverage | use |
| initiate | start |
| terminate | stop |
| delete | remove |
| render | show |
| execute | do |
| maintain | keep |

### Examples

| Non-STE | STE | Why |
|---|---|---|
| The linter validates the file and is reporting the errors to the terminal. | The linter validates the file. It reports the errors to the terminal. | "is reporting" is not a listed form of REPORT. |
| The script has written the output to the log before the test starts. | The script wrote the output to the log. Then the test starts. | The present perfect "has written" is not a listed form. |
| The service utilizes a token cache and leverages the parser for each request. | The service uses a token cache. The service parses each request. | "utilize" and "leverage" are not in the dictionary. |
| The parsing of the manifest is done by the loader, and the validating of the schema comes after. | The loader parses the manifest. Then the loader validates the schema. | Gerunds are not listed forms. Name the actor. |
| The migration had deleted the deprecated column and was terminating the open connections. | The migration removed the deprecated column. Then the migration stopped the open connections. | Use REMOVE and STOP. The past perfect and the progressive are not listed. |
| The client will be receiving the streamed records after the broker has been publishing them for one minute. | The broker publishes the records. The client will receive the streamed records after one minute. | Make the simple future with "will" and the base form. "streamed" is a participle used as an adjective. |
| The given options get validated by the gateway, and the removed entries are gotten from the cache. | The gateway validates the given options. The gateway gets the removed entries from the cache. | "get validated" and "are gotten" are not listed forms. |

Code context:

```python
# STE: the loader parses the manifest. Then the loader validates the schema.
manifest = loader.parse(path)      # parse -> parses / parsed / parsed
loader.validate(manifest, schema)  # validate -> validates / validated / validated
```

```javascript
// STE: the service uses a token cache. The service parses each request.
const cache = new TokenCache();          // use -> uses / used / used
app.post("/orders", (req, res) => {
  const order = parseOrder(req.body);    // parse -> parses / parsed / parsed
  res.json(order);
});
```

```go
// STE: the broker publishes the records.
// The client will receive the streamed records after one minute.
func (b *Broker) Publish(rec []byte) error { // publish -> publishes / published / published
    return b.topic.Send(rec)                 // send -> sends / sent / sent
}
```

See also: Rule 3.2, Rule 3.3, Rule 3.4, Rule 1.1, Rule 1.5, and the STE-Code
dictionary (the full list of approved verbs and their allowed forms).

---

## Rule 3.2 — Use only these verb forms and tenses of verbs

Approved forms and tenses:

- The infinitive form
- The imperative form (command form)
- The simple present tense
- The simple past tense
- The simple future tense
- The past participle form (as an adjective)

| Infinitive | Imperative | Simple present | Simple past | Simple future | Past participle (adj) |
|---|---|---|---|---|---|
| (To) parse (regular) | Parse + object | you/we/they parse; it parses | you/we/they parsed; it parsed | will parse | the parsed file |
| (To) write (irregular) | Write + object | you/we/they write; it writes | you/we/they wrote; it wrote | will write | the written log |
| (To) build (irregular) | Build + object | you/we/they build; it builds | you/we/they built; it built | will build | the built artifact |
| (To) send (irregular) | Send + object | you/we/they send; it sends | you/we/they sent; it sent | will send | the sent request |
| (To) validate (regular) | Validate + object | you/we/they validate; it validates | you/we/they validated; it validated | will validate | the validated token |

Not approved:

- The present perfect (have/has parsed)
- The past perfect (had parsed)
- The present or past progressive (is/was parsing)
- The future progressive (will be parsing)
- The perfect progressive (has been parsing, had been parsing)
- The gerund used as a verb with an auxiliary (is parsing, keeps parsing)
- All other complex verb constructions

### How to select the correct form

1. Infinitive — after a modal verb or to state a purpose: "Use this flag to parse the file."
2. Imperative — for each step of a procedure: "Parse the file. Write the log."
3. Simple present — for a general fact, a repeated action, or system behavior: "The parser reads the file."
4. Simple past — for an action that is complete: "The build failed."
5. Simple future — "will" plus the base form: "The job will start at 02:00."
6. Past participle — only as an adjective before a noun: "the parsed file".

### How to correct an unapproved form

| Unapproved | Correction |
|---|---|
| has parsed (present perfect) | parsed (simple past) |
| had parsed (past perfect) | simple past in two sentences joined with "Then" |
| is parsing, was parsing (progressive) | simple present or simple past; add "at the same time" for concurrent actions |
| will be parsing (future progressive) | will parse (simple future) |
| is being parsed (passive progressive) | name the actor and use the active voice (Rule 3.6) |

### Examples

| Non-STE | STE |
|---|---|
| The linter has found three errors in the source file. | The linter found three errors in the source file. |
| The server was processing the request when the timeout occurred. | The server processed the request. Then the timeout occurred. |
| The framework had already initialized the connection pool before the query started. | The framework made the connection pool. Then the query started. |
| The scheduler is deploying the build to production while the tests are running. | The scheduler sends the build to production. The tests run at the same time. |
| The cache has been keeping the serialized records since the service started, and the client will be reading them after the restart. | The cache keeps the serialized records. The client will read the records after the restart. |
| To be parsing the configuration file, the loader must be having read access to the directory. | To parse the configuration file, the loader must have read access to the directory. |
| You should be setting the timeout value and then you will be restarting the service. | Set the timeout value. Then start the service again. |
| The payload is being validated by the gateway and the deprecated field gets removed by the migration. | The gateway validates the payload. The migration removes the deprecated field. |
| The written log and the parsed manifest are showing that the build had completed with the given options. | The written log and the parsed manifest show that the build completed with the given options. |
| We have been building the release artifact and the CI pipeline will have run the tests by the time you review the pull request. | We built the release artifact. The CI pipeline will run the tests. Then you can review the pull request. |
| If the connection drops, the client is retrying the request until the server responds. | If the connection drops, the client retries the request. Then the server responds. |

Code context:

```bash
# STE: one imperative step for each line
# Set the timeout value.
export REQUEST_TIMEOUT=30
# Then start the service again.
systemctl restart api.service
```

```python
# STE: the server processed the request. Then the timeout occurred.
try:
    response = server.process(request)   # process -> processes / processed / processed
except TimeoutError:
    log.write("request timeout after 30 s")
```

```yaml
# .github/workflows/ci.yml
# STE: we built the release artifact. The CI pipeline will run the tests.
jobs:
  build:
    steps:
      - run: make release
  test:
    needs: build
    steps:
      - run: make test
```

See also: Rule 3.1, Rule 3.3, Rule 3.4, Rule 3.5, Rule 3.6, Rule 1.1.

---

## Rule 3.3 — Use the past participle form as an adjective

When you use the past participle form as an adjective, it shows the condition of
something. This is not passive voice. Use the past participle of an approved verb
as an adjective:

- Before a noun
- After a form of "to be", "to become", or "to stay"

Do not use the past participle form if it is not in the STE-Code dictionary. Some
approved adjectives in the dictionary are past participles of verbs that are not
approved; their part of speech is "(adj)", so you can use them.

### How to know that the participle is an adjective and not passive voice

1. The word gives the condition of the thing, not an action that an actor does.
2. You can put the word directly before the noun: "the parsed file", "the deprecated method", "the closed connection".
3. You can put the word after "is", "becomes", or "stays": "the cache is initialized", "the endpoint becomes deprecated", "the record stays locked".
4. If the sentence names an actor and an action ("the file was parsed by the loader"), the sentence is passive voice. Write the active voice instead (Rule 3.6).

### Approved code-domain past participles used as adjectives

| Past participle (adj) | Example noun phrase | Condition that it shows |
|---|---|---|
| parsed | the parsed manifest | The parser read the file. |
| serialized | the serialized record | The record is in a transport format. |
| deserialized | the deserialized object | The object is in memory again. |
| initialized | the initialized cache | The cache is ready for use. |
| deprecated | the deprecated method | The method is old. Do not use it. |
| allowed | the allowed memory | The limit that the configuration gives. |
| corrupted | the corrupted index | The data is not correct. |
| locked | the locked row | Another transaction holds the row. |
| written | the written log | The log file is on disk. |
| given | the given options | The options that the caller sends. |
| built | the built artifact | The build made the artifact. |
| signed | the signed token | The token has a valid signature. |

### Cautions

- Do not make a new past participle from an unapproved verb. Write "the removed branch", not "the deleted branch", when "delete" is not in the dictionary.
- Do not use a past participle as a verb with "have", "has", or "had" (Rule 3.2).
- Do not put more than one past participle before the same noun. Split a difficult phrase into two short sentences.
- Prefer the plain word: "started" not "commenced"; "used" not "utilized" or "leveraged"; "stopped" not "terminated".

### Correct use (adjective)

| STE | Why it is correct |
|---|---|
| Inspect all fields of the deserialized object for corruption. | "deserialized" is an adjective before the noun "object". |
| When the cache is fully initialized, start the worker threads. | "initialized" comes after "to be" and gives a condition. |
| Do not exceed the allowed memory for the buffer. | "allowed" is an approved adjective. |
| Make sure that the input values are not corrupted. | "corrupted" is an approved adjective. |

### Correction pairs

| Non-STE | STE |
|---|---|
| The parsed file was processed by the loader. | The parsed file is ready for the loader. |
| The method has been deprecated by the API team in release 4.2. | The method is deprecated in release 4.2. Do not use the deprecated method in new code. |
| After the record gets locked, the transaction which was started earlier is being committed. | The transaction writes the locked record. Then the transaction ends. |
| The signed token which had been given to the client is validated by the gateway on each request. | The gateway validates the signed token on each request. |
| When the index becomes corrupted it will have to be being rebuilt by the maintenance job. | When the index becomes corrupted, the maintenance job makes the index again. |
| The build artifact stays uncompiled until the pipeline has compiled the modified sources. | The artifact stays unbuilt until the pipeline builds the modified sources. |
| The user is shown a warning if the uploaded configuration file was found to be malformed. | The CLI shows a warning if the uploaded configuration file is malformed. |
| All of the returned records had already been serialized before the response was sent. | The API sends the serialized records in the response. |
| Make sure that the written log and the given options are not being modified by the plugin. | Make sure that the plugin does not change the written log or the given options. |

Code context:

```go
// STE: "initialized" comes after "is" and gives the condition of the cache.
if cache.IsInitialized() {
    pool.Start(workerCount)
}
```

```sql
-- STE: the transaction writes the locked record. Then the transaction ends.
BEGIN;
SELECT * FROM orders WHERE id = 42 FOR UPDATE;  -- the locked row
UPDATE orders SET status = 'sent' WHERE id = 42;
COMMIT;
```

```javascript
// STE: the gateway validates the signed token on each request.
app.use((req, res, next) => {
  const signedToken = req.headers.authorization; // the signed token
  if (!gateway.validate(signedToken)) {
    return res.status(401).send("the signed token is not valid");
  }
  next();
});
```

See also: Rule 3.1, Rule 3.2, Rule 3.4, Rule 3.5, Rule 3.6, Rule 1.1.

---

## Rule 3.4 — Do not use auxiliary verbs to make complex verb constructions

Do not use the past participle form as a verb together with the auxiliary verb
"have". That construction makes a tense that is not approved.

Do not use auxiliary verbs ("have", "be", "will", "can", "must", "should",
"is to be") with a past participle to build compound tenses or the passive voice.
Write the action with a simple, approved verb form instead:

- Use the simple past instead of "have/has/had + past participle".
- Use the active voice with a clear agent instead of "be + past participle" (Rule 3.6).
- Use the imperative form for instructions instead of "is to be + past participle".
- Use "you can + base verb" instead of "can be + past participle" when the reader is the agent.
- Use "will + base verb" with a named agent instead of "will be + past participle + by + agent".

When a compound construction seems unavoidable, split it into separate simple
sentences. Rule 3.2 lists the only approved forms.

### Conversion table

| Construction | Non-STE | STE |
|---|---|---|
| Present perfect | The build has compiled the module before the test runs. | The build compiled the module. Then the test runs. |
| "is to be" | The migration is to be run before you deploy the service. | Before you deploy the service, run the migration. |
| "can be" | The cache can be cleared. | You can clear the cache. |
| "must be" | The timeout must be set before the job starts. | Set the timeout before the job starts. |
| "will be ... by" | The report will be generated by the scheduler. | The scheduler will generate the report. |
| Present perfect passive | The connection pool has been created before the first query is sent. | The connection pool was created. Then the first query is sent. |
| "must be" (procedure) | The configuration file must be validated before the server starts. | Validate the configuration file before the server starts. |
| "are to be" | The user credentials are to be encrypted at rest and the key is rotated monthly. | Encrypt the user credentials at rest. Rotate the key every month. |
| "can be ... by" | The log entries can be exported to a CSV file by the admin. | The admin can export the log entries to a CSV file. |
| "will be ... by" | An error message will be shown by the validator if the input is empty. | The validator will show an error message if the input is empty. |
| Past perfect passive | The temporary files had been deleted by the cleanup task before the backup started. | The cleanup task removed the temporary files. Then the backup started. |

See also: Rule 3.2, Rule 3.3, Rule 3.5, Rule 3.6.

---

## Rule 3.5 — Use the "-ing" form only as a technical noun or as a modifier in a technical noun

In code documentation, a word that has an "-ing" form can be part of a verb, an
adjective, a noun, or a long group of modifiers. These functions cause ambiguity
and long sentences. Therefore an "-ing" word is not permitted as a verb.

Use an "-ing" word only as a technical noun (for example, in a heading) or as a
modifier inside a technical noun.

### Approved "-ing" words in STE-Code

| Part of speech | Words |
|---|---|
| Nouns | logging, monitoring, routing, servicing |
| Adjectives | matching, missing, remaining |
| Pronoun | something |
| Preposition | during |

### Why the progressive verb form is not approved

Rule 3.2 lists the only permitted forms: infinitive, imperative, simple present,
simple past, simple future, and past participle as an adjective. The progressive
("is running", "are deploying", "was processing") is not on that list. Replace
the progressive with the simple present or the simple past, and break a long
continuous clause into short sentences.

The "-ing" form also hides auxiliary constructions that Rule 3.4 forbids. Do not
write "the service is starting and then it is logging the request". Write "The
service starts. Then it logs the request."

### Approved "-ing" technical nouns (headings and titles)

Logging · Monitoring · Testing and Fault Isolation · Handling · Packaging ·
Shipping · Troubleshooting · Building · Deployment

### Approved "-ing" modifiers (inside a technical noun)

logging service · monitoring agent · routing table · switching relay ·
caching layer · building pipeline · binding configuration · streaming endpoint ·
rendering engine

Do not pull the "-ing" word out of the technical noun and use it as a verb. "The
caching layer stores the result" is approved. "The layer is caching the result"
is not.

### Correction pairs

| Non-STE | STE |
|---|---|
| When you are running this script, obey all the safety checks. | When you run this script, obey all the safety checks. |
| While the deployment is starting, you must watch the logs and you must not stop the process because stopping it during startup can corrupt the state file. | The deployment starts. While it starts, watch the logs. Do not stop the deployment. If you stop the deployment during startup, the state file can become corrupt. |
| The background worker is processing the queue and it is writing the results to the cache while the main thread is waiting for the response, causing the request to time out and the user to see an error. | The background worker processes the queue. It writes the results to the cache. The main thread waits for the response. If the main thread waits too long, the request times out and the user sees an error. |
| Be careful while the process is starting. | Be careful while the process starts. |
| The function is returning the value while the cache is loading the entry, which makes the result incorrect during the first request. | The function returns the value. The cache loads the entry. During the first request, the result is incorrect. |
| The matching algorithm is comparing the remaining items during the iteration and it is removing the missing records from the list. | The matching algorithm compares the remaining items during the iteration. It removes the missing records from the list. |
| Something going wrong during the migration can make the database stay in a broken state. | If something goes wrong during the migration, the database can stay in a broken state. |

### Long "-ing" clauses become vertical lists

Non-STE:

> A script opening a socket without checking the firewall rules and sending data
> to an unknown host, using an unverified certificate without reading the
> security policy, is in danger of causing a breach and thus exposing private
> keys and credentials.

STE:

> Before you open a socket, obey these precautions: (1) Read the security policy.
> (2) Make sure that the firewall rules allow the connection. (3) Verify the host
> certificate. (4) Get the correct credentials to send data to the host. If you do
> not obey these precautions, a breach of private keys and credentials can occur.

Non-STE:

> Developers committing code without running the test suite and pushing directly
> to the main branch, ignoring the review policy, risk breaking the build and
> therefore blocking the release for all team members.

STE:

> Before you commit code, obey these precautions: (1) Run the test suite. (2) Make
> sure that the tests pass. (3) Open a review before you merge to the main branch.
> If you do not obey these precautions, you can break the build and block the
> release for all team members.

See also: Rule 3.2, Rule 3.4, Rule 1.5.

---

## Rule 3.6 — Use the active voice

Use the active voice in all code documentation. In descriptive writing, the
passive voice is permitted only when the agent (the person, service, or component
that does the action) is unknown.

In the active voice, the subject does the action. The reader immediately knows
who or what performs the operation.

- Active: The middleware parses the API response.
- Passive: The API response is parsed by the middleware.

### The "by" test

Ask "by whom or by what?" after the verb phrase. If the sentence answers the
question, the sentence is passive.

- *The data was encrypted…* → by the crypto module. (Passive.)
- *The file was saved.* → by the application. (Passive, agent omitted.)
- *The file is saved.* (Not passive — a condition, a past participle used as an adjective. See Rule 3.3.)

### Four conversion methods

| Method | Use it when | Non-STE | STE |
|---|---|---|---|
| 1 — Move the agent to the subject | A "by"-phrase names the agent | The API response is parsed by the middleware. | The middleware parses the API response. |
| 2 — Change an infinitive to an active verb | A purpose clause hides the actor | To calculate the memory usage from these values. | The profiler calculates the memory usage from these values. |
| 3 — Use the imperative | Procedural text; the reader is the agent | The dependencies can be installed with the following command. | Install the dependencies with this command: `npm install` |
| 4 — Insert "you" or "we" | No agent is given | The configuration file can be edited with a text editor. | You can edit the configuration file with a text editor. |

Use "you" when the agent is the reader. Use "we" when the agent is your project
or organization.

### Method 1 in context — request pipeline README

Non-STE:

```markdown
## How the request pipeline works

After the client sends a request, the raw HTTP body is read by the server.
The API response is parsed by the middleware. The parsed data is then
validated by the schema checker before the controller receives it.
```

STE:

```markdown
## How the request pipeline works

After the client sends a request, the server reads the raw HTTP body.
The middleware parses the API response. The schema checker then validates
the parsed data before the controller receives it.
```

### Method 2 in context — a profiling docstring

Non-STE:

```python
def report_memory(samples):
    """To calculate the memory usage from these values. The peak is
    returned as a percentage of the allocated heap."""
```

STE:

```python
def report_memory(samples):
    """Calculate the memory usage from these values. Return the peak
    as a percentage of the allocated heap."""
```

### Method 3 in context — a contributing guide

Non-STE:

```markdown
## Setup

The dependencies can be installed with the following command. The test
suite can then be run from the same directory.
```

STE:

```markdown
## Setup

Install the dependencies with this command:

    npm install

Then run the test suite from the same directory:

    npm test
```

### Method 4 in context — a getting-started page

Non-STE:

```markdown
## First run

The configuration file can be edited with a text editor. The server
can be started after you save your changes.
```

STE:

```markdown
## First run

You can edit the configuration file with a text editor. After you save
your changes, you can start the server.
```

### When the agent is unknown

- Passive (correct): During the network request, the data was corrupted. The agent is unknown.
- Active (correct): During the network request, something corrupted the data.
- Active (incorrect): The network request corrupted the data. "network request" is not the correct agent, so the sentence becomes technically wrong.

### Further correction pairs

| Non-STE | STE |
|---|---|
| The database connection is established by the connection pool at startup. | The connection pool establishes the database connection at startup. |
| The test results can be viewed in the terminal output. | You can see the test results in the terminal output. |
| The configuration is loaded by the bootstrap routine. | The bootstrap routine loads the configuration. |
| The linting errors are reported by the linter. | The linter reports the linting errors. |
| The coverage report is generated by the coverage tool. | The coverage tool makes the coverage report. |

## Rule 3.6 by document type

### README files

A README mixes procedural text (installation, build, usage) and descriptive text
(overview, features, architecture). Use the imperative in procedural sections and
a named agent in descriptive sections.

| Non-STE | STE |
|---|---|
| The package can be installed with pip install. | Install the package with this command: `pip install .` |
| Support for WebSocket connections is provided by this library. | This library supports WebSocket connections. |

```markdown
## Installation

Install the package with this command:

    pip install .

Create a virtual environment before you install the package.
```

### API reference and docstrings

| Non-STE | STE |
|---|---|
| The input string is validated and a boolean is returned by this method. | This method validates the input string and returns a boolean. |
| The URL is transformed by the callback before the request is sent. | The callback transforms the URL before the client sends the request. |
| A `Promise<User>` is returned by this function. | This function returns a `Promise<User>`. |
| """A hash of the input data is computed and then it is returned as a hex string.""" | """Compute a hash of the input data. Return the hash as a hex string.""" |

### Code comments

| Non-STE | STE |
|---|---|
| // The buffer is flushed before new data is written. | // The writer flushes the buffer before it writes new data. |
| // The connection is closed by the finally block. | // The finally block closes the connection. |

### Commit messages

| Non-STE | STE |
|---|---|
| The authentication bug was fixed. | Fix the token refresh in the authentication middleware. |
| Rate limiting was added to the API endpoints. | Add rate limiting to the API endpoints. |

### Error messages

| Non-STE | STE |
|---|---|
| An invalid configuration value was encountered while the file was being parsed. | The parser found an invalid configuration value at line 12. |
| The request was rejected by the rate limiter. | The rate limiter rejected the request. |

## Rule 3.6 by paradigm

### Object-oriented (Java, C++, C#, Python classes)

Classes, methods, and pattern components are the agents.

| Non-STE | STE |
|---|---|
| The dependency is resolved by the container at runtime. | The container resolves the dependency at runtime. |
| New instances are created by the factory method when they are requested by the client. | The factory method creates a new instance when the client requests one. |
| The `validate()` method is called before the data is processed by the handler. | The handler calls the `validate()` method before it processes the data. |

```java
/**
 * The handler calls the validate() method before it processes the data.
 * The handler throws a ValidationException when it rejects the record.
 */
interface RequestHandler { void handle(Request req); }
```

### Functional (Haskell, Elixir, Clojure, Rust)

Functions and combinators are the agents.

| Non-STE | STE |
|---|---|
| Each element in the list is transformed by the `map` function. | The `map` function transforms each element in the list. |
| The input is filtered, then mapped, and finally the result is reduced to a single value. | The `filter` function removes invalid items. The `map` function transforms each item. The `reduce` function combines the results into a single value. |
| Two functions are composed into a new function by the `compose` combinator. | The `compose` combinator combines two functions into a new function. |

```clojure
;; The filter function removes invalid items. The map function transforms
;; each item. The reduce function combines the results into a single map.
(->> items (filter valid?) (map enrich) (reduce merge {}))
```

### Procedural (C, Go, Bash)

The script, the tool, or the function is the agent. Use the imperative in
procedural text.

| Non-STE | STE |
|---|---|
| The file is opened, the contents are read, and the connection is closed. | The script opens the file. It reads the contents. Then it closes the connection. |
| Environment variables are checked before the build process is started. | The script checks the environment variables. Then it starts the build process. |
| The log file can be rotated with the --rotate flag. | Use the --rotate flag to rotate the log file. |

```makefile
# The script checks the environment variables. Then it starts the build.
# Use the --rotate flag to rotate the log file.
build:
	./configure && $(MAKE)
```

### Declarative (SQL, Terraform, Kubernetes YAML, Dockerfile)

The declaration does not act. The tool or engine that reads the declaration acts.

| Non-STE | STE |
|---|---|
| An AWS VPC with three subnets is provisioned by this Terraform module. | This Terraform module provisions an AWS VPC with three subnets. |
| All rows with a status of 'active' are selected by this query. | This query selects all rows with a status of 'active'. |
| Three replicas of the pod are maintained by the deployment controller. | The deployment controller maintains three replicas of the pod. |
| # The base image is set to Ubuntu 22.04. | # Use Ubuntu 22.04 as the base image. |

NOTE: YAML comments and Dockerfile comments are procedural. Use the imperative
form and the active voice, because they instruct the reader or the build engine.

```sql
-- This query selects all rows with a status of 'active'. The aggregate
-- then counts the matching accounts.
SELECT count(*) FROM accounts WHERE status = 'active';
```

### Systems programming (Rust ownership, C memory, concurrency)

The allocator allocates. The function takes ownership. The mutex locks. The
channel sends.

| Non-STE | STE |
|---|---|
| The memory block is allocated by the allocator and a pointer is returned. | The allocator allocates the memory block. It returns a pointer. |
| Ownership of the string is taken by the `process` function. | The `process` function takes ownership of the string. |
| Access to the shared state is controlled by the mutex. | The mutex controls access to the shared state. |

```rust
// The mutex controls access to the shared state. The channel sends the
// value to the worker.
let guard = state.lock().unwrap();
tx.send(guard.clone());
```

## Rule 3.6 — extended examples

### Example 1 — README feature description

Non-STE: Authentication via OAuth2 and JWT tokens is supported by this service.
Rate limiting is applied to all endpoints. Requests are logged to a centralized
logging system.

STE: This service supports authentication with OAuth2 and JWT tokens. It applies
rate limiting to all endpoints. It sends request logs to a centralized logging
system.

The original has three consecutive passive constructions. The STE version
establishes "this service" as the agent once, then uses active verbs.

### Example 2 — API method documentation

Non-STE: `createUser(payload)` — A new user is created with the provided payload.
The payload is validated before the user record is inserted into the database. A
`User` object is returned upon success.

STE: `createUser(payload)` — Create a new user with the provided payload. The
method validates the payload. Then it inserts the user record into the database.
It returns a `User` object on success.

The reader of the original cannot tell whether the method, the database, or the
caller validates the payload.

### Example 3 — class docstring

```python
class ConnectionPool:
    """Manage a pool of database connections. The class lends a connection
    when a request arrives. It returns the connection when the request is
    complete. The reaper thread closes idle connections."""
```

### Example 4 — commit message

Non-STE: The memory leak in the image processing pipeline was fixed. Redundant
allocations were removed and the buffer pool was refactored.

STE: Fix the memory leak in the image processing pipeline. Remove redundant
allocations. Refactor the buffer pool.

### Example 5 — error message

```json
{
  "level": "error",
  "msg": "The token validator found a malformed token. The server rejected the request."
}
```

### Example 6 — configuration comment

```toml
# This setting controls the maximum number of concurrent connections.
# The server queues requests beyond this limit.
max_connections = 100
```

## Rule 3.6 — edge cases

### Edge case 1 — unknown agent (the standard exception)

When the agent is genuinely unknown, the passive voice is correct. In code
documentation this applies to:

- Unexpected data corruption with no identifiable cause
- External network failures where the remote endpoint is unknown
- Hardware faults that appear as software errors
- Race conditions where the exact sequence of events is not reproducible

- Correct (passive): The data was corrupted before the checksum was computed.
- Incorrect (active): Something corrupted the data before the checksum was computed. ("something" adds no information.)

NOTE: Use "something" as the agent only when you can describe the type of agent
(for example, "some process", "some external service"). If you cannot describe
the type, keep the passive voice.

### Edge case 2 — topic-comment structure in descriptive text

When the object is the established topic of the paragraph and the agent is
irrelevant, the passive voice can be clearer.

- Active (awkward): The developer stores the configuration file in the `/etc/myapp` directory.
- Passive (acceptable): The configuration file is stored in the `/etc/myapp` directory.
- Active (correct for a responsibility section): You must store the configuration file in the `/etc/myapp` directory.

Decision rule: if the paragraph topic is the object and an active rewrite would
introduce a distracting agent, use the passive voice. If the paragraph topic is
the agent, use the active voice.

### Edge case 3 — quotations from RFCs and specifications

Keep the passive voice inside a quotation and add a NOTE that identifies the
non-STE source. Do not rewrite the quotation. The rule applies only to the text
that you write.

> NOTE: The following description quotes RFC 7230. The passive voice in the
> quotation is from the original RFC text.
>
> > "The request message is parsed by the server into its component parts."

### Edge case 4 — framework-generated documentation

If you control the generator template (a Sphinx theme, a JSDoc template),
configure it to use the active voice. If you do not control the output, add a
NOTE at the top of the generated document.

> NOTE: This document was generated by [tool name]. Some sentences use the
> passive voice. Refer to the source code comments for STE-Code compliant
> descriptions.

### Edge case 5 — passive voice in established error message standards

Do not rewrite error strings from external systems (POSIX strings, HTTP reason
phrases, database error codes). The rule applies only to the messages that you
write.

- Your message (STE): The server cannot connect to the database at host:port.
- System message (unchanged): Connection refused.

## Rule 3.6 — grammar notes

### Structures

```
Active:  Subject (Agent) + Verb + Object (Patient)
Passive: Subject (Patient) + be + Past Participle (+ by + Agent)
```

Active voice gives the agent and the action in the natural reading order. Passive
voice gives the action first and the agent last, or not at all.

### Common passive constructions and their active equivalents

| Passive construction | Active equivalent | Method |
|---|---|---|
| is returned by | returns | 1 — move agent to subject |
| can be used to | you can use … to | 4 — insert "you" |
| is configured by | configures | 1 |
| is called when | calls | 1 |
| was added in version | (we) added … in version | 4 — insert "we" |
| should be installed | install (imperative) | 3 |
| is designed to | (we) designed … to | 4 |
| has been deprecated | (we) deprecated | 4 |
| will be removed in | (we) will remove … in | 4 |

### Passive with a modal verb

Keep the modal verb and move the agent to the subject position.

| Passive with modal | Active with modal |
|---|---|
| The file can be opened with this command. | You can open the file with this command. |
| The setting must be configured before startup. | You must configure the setting before startup. |
| The output will be written to stdout. | The program will write the output to stdout. |

### Structural patterns

| Pattern | Input structure | Output structure | Example |
|---|---|---|---|
| A — agent in a "by"-phrase (Method 1) | Patient + be + past participle + by + Agent | Agent + active verb + Patient | The token is validated by the auth middleware. → The auth middleware validates the token. |
| B — no agent, procedural (Method 3) | Patient + modal + be + past participle | Imperative verb + Patient | The dependencies should be installed before the build. → Install the dependencies before the build. |
| C — no agent, descriptive (Method 4) | Patient + be + past participle | You/We + active verb + Patient | The configuration file is stored in the config directory. → You must store the configuration file in the config directory. |

### Work together with the Canonical Synonym Table

When you convert a passive sentence, also check the replacement verb against the
Canonical Synonym Table.

| Non-STE | STE | Fixes applied |
|---|---|---|
| The result is used by the downstream pipeline. | The downstream pipeline uses the result. | Passive → active (Rule 3.6). |
| The error is displayed on the console by the logger. | The logger shows the error on the console. | Passive → active; "display" → "show" (Rule 1.1). |
| The report is generated by the scheduler every night. | The scheduler makes the report every night. | Passive → active; "generate" → "make" (Rule 1.1). |

### Rule 3.6 cross-references

- Rule 1.1 — the new agent must be an approved word or a permitted technical noun.
- Rule 1.5 — technical nouns that name code entities (middleware, validator, container, allocator, mutex) are permitted as agents. The agent must be a real code entity, not a vague abstraction.
- Rule 1.12 — the active verb is often a technical verb (parse, compile, deploy, render, query, allocate). Use its approved simple form.
- Rule 3.1 and Rule 3.2 — active voice sentences use the simple tenses. Converting to active voice also simplifies the tense.
- Rule 3.4 — the passive voice uses the auxiliary "be" plus a past participle. Converting to active voice removes the auxiliary.
- Rule 3.5 — a passive progressive ("is being parsed") breaks both Rule 3.5 and Rule 3.6. Convert to active voice first, then check the remaining "-ing" forms.
- Rule 3.7 — sentences must not exceed 20 words in procedural text and 25 words in descriptive text. Converting to active voice usually shortens the sentence. If the sentence is still too long, split it.

---

<!-- rules-sec4.md -->

# Level 3 — STE-Code Section 4: Sentence Structure (Rules 4.1–4.5)

This slice covers the five Section 4 rules that govern sentence-level structure in
code documentation: one topic per sentence, no omitted words or contractions,
vertical lists, connecting words, and articles / demonstrative adjectives.

Apply these rules to docstrings, API references, README sections, commit messages,
and code comments. This is the Level 3 (high-fidelity) form: every rule is complete
with code-domain examples, paradigm guidance, edge cases, grammar notes, and a
checklist. Use the checklist at the end of each rule as a quick pass before you
publish documentation.

Each rule below gives: the requirement, code-domain examples, paradigm-specific
guidance, edge cases, grammar notes, and a summary checklist.

---

## Rule 4.1 — One Topic Per Sentence, No Abstract Text

**Requirement**
- Descriptive text (a class, module, or type description): each sentence has one
  topic and does not use the imperative mood. Add detail in the sentences that follow.
- Procedural text (an API method or function description): one instruction per
  sentence in the imperative mood.
- Never write abstract sentences. Show how to use a function or how a module
  operates. State the action or the measured result — not a vague property.

**Code examples — descriptive (one topic per sentence)**
- Non-STE: `The HttpClient class has two internal buffers connected together and linked with callbacks between the request handler and the response dispatcher.`
- STE: `The HttpClient class has two internal buffers. The internal buffers are connected together with callbacks. These callbacks link the request handler to the response dispatcher.`

**Code example — descriptive docstring (Java)**
```java
/**
 * STE:
 * The ConnectionPool manages a set of reusable TCP connections.
 * The connections are created lazily when the pool starts.
 * Each connection is validated when the caller checks it out.
 * Each connection is reset before the caller returns it to the pool.
 * The caller always receives a clean socket from the pool.
 */
public class ConnectionPool { /* ... */ }
```

**Code examples — avoid abstract statements**
- Non-STE: `No null values are permitted.` → STE: `Make sure that the function does not return a null value.`
- Non-STE: `Different payload sizes will change the parse time.` → STE: `When the payload size increases, the parse time will increase.` / `The parse time is 2 milliseconds for a payload of 1 KB.`

**Code example — avoid abstract statements (Python docstring)**
```python
# Non-STE:
def read_config(path: str) -> dict:
    """Loads the configuration. Returns None on error."""
    ...

# STE:
def read_config(path: str) -> dict:
    """Load the configuration from the file at the given path.
    Return an empty dictionary if the file does not exist.
    Do not return null. Raise ConfigError if the file is not valid."""
    ...
```

**Code example — procedural (one instruction per sentence, imperative)**
```python
# STE:
# 1. Build the HttpClient with the default configuration.
# 2. Set the timeout to 30 seconds.
# 3. Call the send method with the request object.
# 4. Check the response status code.
# 5. Read the response body into a string.
def send_request(req: Request) -> str:
    ...
```

**Code example — procedural (Bash CLI)**
```bash
# STE:
# 1. Export the API token to the TOKEN variable.
# 2. Select the staging environment with the --env flag.
# 3. Run the deploy script.
# 4. Check the build log for the success message.
```

**Code example — declarative resource (Terraform)**
```hcl
# STE:
# The aws_s3_bucket resource creates a storage bucket for application logs.
# The bucket name is "app-logs".
# The bucket keeps a version of each object that you overwrite.
# The bucket encrypts each object with the AES256 algorithm.
resource "aws_s3_bucket" "logs" {
  bucket = "app-logs"
}
```

**Paradigm guidance**
- Object-Oriented (Java, C++, C#, Python): class docs are descriptive (one short sentence, one topic); method descriptions are numbered imperative steps.
- Functional (Haskell, Elixir, Clojure, Rust): type signatures descriptive (one property per sentence); effectful functions use procedural steps.
- Procedural (C, Go, Bash): function docs are a sequence of steps; each step is one imperative sentence with one instruction.
- Declarative (SQL, Terraform, Kubernetes YAML): resource docs descriptive; describe what the configuration does, one fact per sentence.
- Systems (Rust ownership, C memory): describe invariants and ownership rules in descriptive sentences; use imperative steps only for unsafe operations.

**Edge cases**
- Generated documentation (JSDoc, Sphinx, `go doc`): apply Rule 4.1 to the source docstrings and comments; fix the source text, not the generated output.
- Single-sentence module summary: the first line conveys the purpose; expand the body with one topic per sentence.
- Safety callouts (BREAKING, DEPRECATED, NOTE): keep the callout to one short sentence; put detail in the paragraph that follows.
- Error messages: one topic; state what failed and, when useful, tell the reader how to fix it in a second sentence. Do not write a vague abstract error such as "Invalid input occurred."
- Commit messages: subject line one topic; each related change its own bullet in the body.
- README sections: one idea per paragraph; one sentence per listed feature.

**Grammar notes**
- Sentence length: max 20 words for procedural, 25 words for descriptive. Code spans, inline code, and URLs do not count.
- Imperative mood: start each procedural step with an imperative verb (call, set, pass, check, start, send, remove, add, make, use, run, build, test, deploy). Avoid "you should" / "the user must."
- Clause nesting: do not nest clauses deeper than two levels; break nested clauses into separate sentences.
- Voice: prefer active for both descriptive and procedural sentences; the subject performs the action.
- Abstract text: replace "performance may vary" with a sentence giving the measured value and the condition.

**Checklist**
- [ ] Max 20 words (procedural) / 25 words (descriptive).
- [ ] One topic or one instruction per sentence.
- [ ] Procedural sentences use the imperative mood.
- [ ] Descriptive sentences do not use the imperative mood.
- [ ] Text is not abstract; shows how to use the code.
- [ ] Each descriptive sentence states one fact in the active voice.
- [ ] Each measurable claim gives the value and the condition.

---

## Rule 4.2 — Do Not Omit Words or Use Contractions

**Requirement**
- Every sentence must have all its parts. Do not omit words or use contractions to
  make a sentence shorter; a shorter sentence is not necessarily easier to read.
- Do not omit nouns (the reader will not know which code element the sentence refers to).
- Do not omit verbs (the reader will not understand the action performed).
- Do not omit the subject (the reader will not know which function, class, or module acts).
- Do not omit articles (the, a, an); omitted articles cause ambiguity.
- Do not use contractions. Write "do not" not "don't", "is not" not "isn't",
  "are not" not "aren't", "cannot" not "can't", "will not" not "won't".

**Code examples**
- Subject: Non-STE: `Can be a maximum length of 256 characters.` → STE: `The input string can have a maximum length of 256 characters.`
- Verb: Non-STE: `The return value a boolean that indicates success.` → STE: `The return value is a boolean that indicates success.`
- Noun: Non-STE: `The function returns the parsed.` → STE: `The function returns the parsed configuration object.`
- Article: Non-STE: `` `validate` function checks input parameter. `` → STE: `The \`validate\` function checks the input parameter.`
- Contraction: Non-STE: `The method doesn't throw an exception when the input is null.` → STE: `The method does not throw an exception when the input is null.`
- Noun the verb acts on (parallel): Non-STE: `Remove the bolt and stop.` → STE: `Remove the bolt and the stop.`
- Conditional verb: Non-STE: `If installed, remove the shims.` → STE: `If shims are installed, remove them.`
- Safety subject: Non-STE: `BREAKING: MAKE SURE THAT THE DATABASE IS BACKED UP. IF NOT, THIS CAN CAUSE DATA LOSS.` → STE: `BREAKING: MAKE SURE THAT THE DATABASE IS BACKED UP. A MISSING BACKUP CAN CAUSE DATA LOSS.`

**Code example — do not omit the subject (Python docstring)**
```python
def validate_username(name: str) -> bool:
    """Check whether the user name is valid.

    The user name can have a maximum length of 256 characters.
    The user name must contain only letters, digits, and underscores.
    """
    return len(name) <= 256 and name.isidentifier()
```

**Code example — do not use a contraction (C# XML doc)**
```csharp
/// <summary>
/// Reads the next record from the stream.
/// </summary>
/// <remarks>
/// The method does not throw an exception when the input is null.
/// The method returns null when the end of the stream is reached.
/// </remarks>
public Record? ReadNext(Stream? input) { ... }
```

**Code example — contraction in a warning (README)**
```markdown
> **WARNING**
> If your hands are wet, do not touch the USB power adapter.
> The adapter supplies current that can cause injury.
> Keep the adapter away from water while it is connected.
```

**Paradigm guidance**
- Object-Oriented: method return descriptions often omit the subject — write "The method returns…"; constructor docs often omit the verb — write "The constructor creates…"; getter/setter comments often omit the article — write "The getter returns the value of the field."
- Functional (Haskell, Elixir, Clojure, F#): pattern-match docs often omit verbs — write each arm as a full sentence with a verb; type-variable descriptions often omit subjects — add "The type variable represents…"; monad-law notes often omit articles — write "The first law states that…"
- Procedural (C, Go, Bash, Rust): function synopses in headers often omit articles and subjects — write "The function reads a configuration file."; makefile/shell comments often omit the verb — write "The script removes the build directory."
- Declarative (SQL, Terraform, Kubernetes YAML, Ansible): comments and resource descriptions often omit verbs and articles — write each as a full sentence with subject and verb. For a SQL view: "The view returns the active users." For a Terraform block: "The resource creates a storage bucket."
- Systems (Rust unsafe, C memory): safety docs with omitted subjects cause real bugs. Always write subject, verb, and articles in full — e.g. "The caller must ensure that the pointer is valid."

**Edge cases**
- Commit message summary line: the 72-char limit makes full sentences hard; the summary may use a relaxed form, but the body must follow the rule strictly.
- CLI help text: terminal width causes omitted articles/subjects; long-form docs must use full sentences. CLI help may relax to `rm FILE`; the manual page must write "The command removes the file."
- Code token that is also a contraction: a token such as `won't` (test name), `can't` (variable), `it's` (map key) is a technical noun — keep it in backticks, do not expand. Write "The test `won't` checks the failure path," not "The test `will not` checks the failure path."
- Error messages and log lines: short error strings may omit articles; the docs that explain the error must use full sentences ("The error means that the connection is closed.").
- Tables and lists: a cell may hold a short phrase; the surrounding prose and the column header must supply the subject and verb. Write the header "The function returns the status code," not "Returns status."

**Grammar notes**
- Write "do not," "is not," "are not," "cannot," "will not," "does not," "did not" in full. No apostrophe contractions.
- Every sentence needs a subject, a verb, and the required articles (the, a, an).
- When you connect two nouns with "and," repeat the article if the two items are different physical or logical things: "Remove the bolt and the stop," not "Remove the bolt and stop."
- Prefer plain dictionary verbs: "check" not "verify," "make" not "create," "get" not "retrieve," "set" not "configure," "remove" not "delete" when the simpler word fits.

**Checklist**
- [ ] Every sentence has a subject, a verb, and the required articles.
- [ ] No words are omitted to make the sentence shorter.
- [ ] No contractions are used (write "do not," "is not," "are not," "cannot," "will not" in full).
- [ ] The reader knows which element performs the action.
- [ ] Parallel nouns joined by "and" each keep their article.
- [ ] Code tokens that look like contractions stay in backticks and are not expanded.

---

## Rule 4.3 — Use a Vertical List for Complex Text

**Requirement**
- When a sentence is long and lists many items (parameters, return fields, error
  codes, configuration options, environment variables, dependencies, test cases) or
  actions, put them in a vertical list.
- Put a colon (`:`) at the end of the introductory sentence, before the first item.
- Identify each item with a number, letter, dash, or bullet.
- Start each item with an uppercase letter.
- Where applicable, use an article before the noun that is the subject of each item.
- Put a period at the end of an item if it is a full sentence (e.g. an imperative
  step like "Set the timeout value"). Do not put a period at the end of a non-sentence
  item (e.g. "The `timeout` parameter that controls the delay").
- Do not put a comma or semicolon at the end of an item.
- Put a period at the end of the last item.
- Use vertical lists in procedural and descriptive docs, but do not mix imperative
  instructions and descriptive statements in the same list.
- In safety instructions, include negative commands (DO NOT) where necessary for each item.
- Each item must connect clearly to the introductory text. Test by reading
  "Introductory text [item]" as one sentence.
- Do not nest a second vertical list inside the primary list. Use the same level for
  all items. If a sub-item needs its own list, start a new introductory sentence after
  the parent item, or use a table or a separate list under a new heading.
- An item can contain a verb and not be a full sentence; then it takes no period.

**Code examples**
- Non-STE: `The UserService constructor accepts the database URL, the cache backend, and the maximum retry count.`
- STE:
```
The `UserService` constructor accepts these parameters:
- The `database_url` for the PostgreSQL connection string.
- The `cache_backend` for session storage.
- The `max_retries` for transient failure handling.
```

**Code example — constructor parameters (Python docstring)**
```python
class UserService:
    """Manage application users and their sessions.

    The UserService constructor accepts these parameters:
    - The database_url for the PostgreSQL connection string.
    - The cache_backend for session storage.
    - The max_retries for transient failure handling.
    """

    def __init__(self, database_url, cache_backend, max_retries=3):
        self.database_url = database_url
        self.cache_backend = cache_backend
        self.max_retries = max_retries
```

**Code example — procedural steps (one type only)**
```
## Deploy the application

To deploy the application, do these steps:
- Set the `DATABASE_URL` environment variable.
- Run the `apply-migrations` command.
- Start the server on port 8080.

The server binds to port 8080 after startup.
```

**Code example — error codes (HTTP API)**
- Non-STE: `The API returns 400 for validation issues, 401 when the token is expired, 403 if permissions are not sufficient, and 404 when the resource is missing.`
- STE:
```
The API returns these error codes:
- `400 Bad Request` for a failed input validation.
- `401 Unauthorized` for an expired or missing token.
- `403 Forbidden` for insufficient permissions.
- `404 Not Found` for a missing resource.
```

**Code example — safety instruction (negative command per item)**
```
CAUTION: WHEN YOU ACCESS THE CONFIGURATION THROUGH THE ADMIN PANEL:
- DO NOT CHANGE THE SECRET KEY.
- DO NOT DISABLE THE AUDIT LOG.
```

**Code example — declarative config fields (YAML)**
```
# The config.yaml file has these top-level fields:
# - The server.port that sets the listen port.
# - The log.level that sets the log verbosity.
# - The database.pool_size that sets the maximum open connections.
# - The features that lists the enabled feature flags.
server:
  port: 8080
log:
  level: info
database:
  pool_size: 20
features:
  - new_checkout
  - dark_mode
```

**Code example — function return codes (Go)**
```go
// The openFile function returns these codes:
// - 0 for a successful open.
// - -1 for a missing path.
// - -2 for insufficient permission.
func openFile(path string) (int, error) {
    if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
        return -1, fmt.Errorf("the path %q is missing", path)
    }
    f, err := os.Open(path)
    if err != nil {
        return -2, fmt.Errorf("the user lacks permission for %q", path)
    }
    defer f.Close()
    return 0, nil
}
```

**Other list types covered by this rule**
- Data-transfer-object fields (object has these fields: `email`, `display_name`, `role`)
- Test cases (the function passes these test cases: accept `"10s"` and return 10 seconds; …)
- Dependencies in a package manifest (`express` for HTTP routing; `pg` for PostgreSQL; `redis` for cache)
- Environment variables (the worker reads these: `LOG_LEVEL`, `QUEUE_URL`, `MAX_WORKERS`)

**Paradigm guidance**
- Object-Oriented: use a vertical list for constructor parameters, public methods, DTO fields, and exceptions a method can send.
- Functional: use a vertical list to document each variant of a sum type or each pattern-match arm.
- Procedural (C, Go, Bash): use a vertical list for function return codes; one item per code and meaning.
- Declarative (SQL, Terraform, YAML): use a vertical list for top-level fields; a separate list for sub-fields of a complex field.
- Systems (Rust, C memory): use a vertical list for ownership or lifecycle rules; one item per constraint.

**Edge cases**
- Nested fields: do not put a second vertical list inside the primary list; describe sub-fields with a new introductory sentence after the parent item, or with a table.
- Generated documentation (JSDoc, Sphinx, rustdoc) may use tables — acceptable; apply Rule 4.3 to prose a human writes.
- Very short lists: a list of two or three items under ~5 words each may stay inline; use a vertical list when each item has more than five words or the inline sentence exceeds 25 words.
- Code blocks in items: put the code block after the item text, indented under the item; the item still starts with an uppercase letter.
- Mixed code and prose: keep the item sentence first (starting uppercase), then add the code block; do not start the item with a code fence.

**Grammar notes**
- Each item must complete the introductory sentence grammatically.
- Use "the" or "a/an" consistently across all items; put the article before the backticks when the item starts with a code identifier.
- A full sentence has a subject and a finite verb. An item with only a verb phrase (e.g. "Set the timeout value") is a full imperative sentence and gets a period. An item such as "The `timeout` parameter that controls the delay" is a relative clause and gets no period until the last item.

**Checklist**
- [ ] The introductory sentence ends with a colon.
- [ ] Each item starts with an uppercase letter.
- [ ] Each item connects to the introductory text.
- [ ] No period on non-sentence items; period on the last item.
- [ ] No mixed procedural and descriptive items in one list.
- [ ] No nested vertical lists.
- [ ] Each code sample (if any) comes after its item sentence.

---

## Rule 4.4 — Use Connecting Words and Connecting Phrases

**Requirement**
- Connecting words and phrases connect a topic in one sentence with an idea in the
  sentence that follows.
- In code documentation they give the writing a logical structure and make technical
  information easy to understand.
- Approved connecting words: "and," "but," "then," "thus."
- Approved connecting phrases: "as a result," "at the same time."
- Demonstrative adjectives (this, these) also connect ideas in related sentences; they
  refer back to a topic named in the previous sentence.
- In procedural docs, use connecting words when an explanation is necessary after a work
  step. In safety instructions, use them to connect related sentences and make the text clear.
- Starting a sentence with "and" or "but" is permitted and encouraged — it creates short,
  independent sentences with an explicit logical link.

**Code examples**
- "and" (two related descriptions):
  - Non-STE: `` `parseInput` validates the request payload and `formatOutput` serializes the response, and they're both called in the handler. ``
  - STE: `The \`parseInput\` function validates the request payload. And the \`formatOutput\` function serializes the response data.`
- "but" (exception or alternative):
  - Non-STE: `These error-handling rules are the minimum necessary for the API layer, although the local project conventions may specify additional ones.`
  - STE: `These error-handling rules are the minimum necessary for the API layer. But the local project conventions can give other necessary error-handling rules.`
- "thus" (logical consequence):
  - Non-STE: `If the validation step fails, the middleware sets an error code on the response object, so the downstream handler gets it and skips processing.`
  - STE: `If the validation step fails, the middleware sets an error code on the response object. Thus, the downstream handler receives the error code and skips the processing step.`
- "as a result" (cause and effect):
  - Non-STE: `When the cache eviction policy runs, expired entries are removed, which frees up capacity for new entries.`
  - STE: `When the cache eviction policy runs, expired entries are removed from the cache. As a result, the cache has free capacity for new entries.`
- "then" (time sequence in a procedure):
  - Non-STE: `Open the database connection, after that run the migration script, and finally start the API server.`
  - STE: `Open the database connection. Then run the migration script. And then start the API server.`
- Demonstrative adjective "this" in procedures:
  - Non-STE: `Tag the deprecated methods with the @deprecated annotation; it helps developers migrate to the new API.`
  - STE: `Tag the deprecated methods with the @deprecated annotation. This annotation will help developers during the migration to the new API.`
- Safety instruction:
  - Non-STE: `Always validate user input in this module because it prevents injection attacks.`
  - STE: `BREAKING: ALWAYS VALIDATE USER INPUT IN THIS MODULE. THIS PRECAUTION WILL PREVENT INJECTION ATTACKS.`
- Missing connection (STE makes the link explicit):
  - Non-STE: `POST /users creates a new user account and returns a 201 status. The response body contains the created user object with an auto-generated ID. The ID can be used in later requests to reference this user.`
  - STE: `A POST request to /users makes a new user account. As a result, the API returns a 201 status code. And the response body contains the created user object with an auto-generated ID. You can use this ID in later requests to refer to the user.`
- "at the same time" (concurrency):
  - Non-STE: `The worker fetches the page and parses it concurrently using asyncio tasks.`
  - STE: `The worker fetches the page from the remote server. At the same time, the parser reads the response stream. And both tasks finish before the timeout.`
- "but" in an error-message description:
  - Non-STE: `The read_file function returns the contents; however, it raises PermissionError when the path is not readable.`
  - STE: `The read_file function returns the contents of the file. But it raises a PermissionError when the path is not readable.`

**Paradigm guidance**
- Object-Oriented: describe class invariants in one sentence; use "thus" to connect them to public-API behavioral guarantees; use "this" to refer to a private field; use "and" to group related methods.
- Functional: describe the input type in one sentence; use "and" to connect happy path to error path; use "thus" to connect a transformation step to the output shape.
- Procedural (C, Go, Bash): describe the allocation step in one sentence; use "then" to introduce initialization; use "as a result" to connect processing to the final state.
- Declarative (SQL, Terraform, YAML): describe the resource spec in one sentence; use "thus" to connect the spec to the reconciliation outcome; use "this" to refer to a named resource.
- Systems (Rust, C memory): describe the ownership rule in one sentence; use "thus" to connect the rule to the compiler guarantee; use "but" to introduce an unsafe escape hatch.

**Edge cases**
- Connecting word that is also a framework name: e.g. the `Then` assertion library, the Rust `and_then` combinator. When the word is a code token in backticks, treat it as a technical noun; the sentence-initial connecting word is not in backticks.
- "Then" ambiguity: use "after" for time or "thus" for logic when ambiguous (do A, then do B = time; if A, then B = logic).
- Generated code comments: this rule applies to documentation you write, not auto-generated comments. Do not edit generated comments to add connecting words.
- Connecting across three or more sentences: limit connecting-word chains to two or three sentences; if more are needed, restructure into a list or a table.
- Connecting word at the start of a section: do not use a connecting word at the very start of a new section to link it to the previous section; the heading provides the connection. Restate the topic so the section stands alone.

**Grammar notes**
- Start a sentence with "and" or "but" to create short, independent sentences with an explicit logical link.
- "Thus" and "as a result" sit at the start of the second sentence; do not use a semicolon before "thus."
- "This" and "these" are demonstrative adjectives when they modify a noun ("this function," "these parameters"); prefer the adjective form with an explicit noun to remove ambiguity.
- When you connect two sentences with "and," keep the two sentences parallel in structure.

**Checklist**
- [ ] Each connecting word links a sentence to the one that follows.
- [ ] Only approved connecting words and phrases are used.
- [ ] Demonstrative adjectives refer back to a clearly introduced topic.
- [ ] No mixed procedural and descriptive modes inside one connected pair.
- [ ] Connecting-word chains do not exceed three sentences.

---

## Rule 4.5 — Use an Article or a Demonstrative Adjective Before a Noun

**Requirement**
- Articles ("the," "a," "an") and demonstrative adjectives ("this," "these") show the
  position of nouns in the sentence. Use them correctly; do not remove them to shorten text.
- Do not use an article in a general statement or before an abstract concept
  ("performance," "scalability," "error handling," "concurrency," "backward compatibility").
- In short sentences, use an article before each noun.
- In a long series of items, use the article only before the first noun in the series.
- When an adjective applies to only one item in a series, repeat the article before each
  item to avoid ambiguity.
- Do not use a definite article before a noun when a code identifier follows it — the
  identifier makes the noun phrase a proper noun (function, class, variable, file,
  environment variable, error code, version tag).
- Use a demonstrative adjective ("this," "these") to connect a noun to the topic of the
  previous sentence; always keep the noun after it — do not write "this" or "these" alone.

**Code examples**
- Article in a short instruction:
  - Non-STE: `Call callback function. Pass response object to handler and set retry flag.`
  - STE: `Call the callback function. Pass the response object to the handler. Then set the retry flag.`
- API reference sentence:
  - Non-STE: `Method reads configuration file and returns settings object.`
  - STE: `The \`load\` method reads the configuration file and returns the settings object.`
- No article in a general statement:
  - Non-STE: `The error handling is important for the production applications. A function throws the error when the input is not valid.`
  - STE: `Error handling is important for production applications. The function throws an error when the input is not valid.`
- Article only before the first noun in a long series:
  - Non-STE: `Delete temporary files, log files, cache entries, and lock files before you start the build.`
  - STE: `Delete the temporary files, log files, cache entries, and lock files before you start the build.`
- Article before each noun when an adjective applies to only one item:
  - Non-STE: `Register the new event listeners, timers, subscriptions, and cleanup callbacks.`
  - STE: `Register the new event listeners, the timers, the subscriptions, and the cleanup callbacks.` (Only the event listeners are new.)
- No article before a noun with a code identifier:
  - Non-STE: `Call the function \`validateInput\` before you send the request.` → STE: `Call function \`validateInput\` before you send the request.` (or `Call the \`validateInput\` function …`)
  - Non-STE: `Set the variable \`LOG_LEVEL\` to \`debug\`.` → STE: `Set variable \`LOG_LEVEL\` to \`debug\`.`
  - Non-STE: `Install the version 3.2.1 of the package.` → STE: `Install version 3.2.1 of the package.`
- Demonstrative adjective for sentence linking:
  - Non-STE: `The function returns a configuration object. Configuration object has three fields: host, port, and timeout.`
  - STE: `The function returns a configuration object. This object has three fields: \`host\`, \`port\`, and \`timeout\`.`
- Article in a commit message / release note:
  - Non-STE: `Fix race condition in scheduler; worker pool now waits for queue drain.`
  - STE: `Fix the race condition in the scheduler. The worker pool now waits for the queue to become empty.`
- Article in an error message / test description:
  - Non-STE: `Input not valid: field must be string.` → STE: `The input is not valid. The \`name\` field must be a string.`
  - Non-STE: `Test verifies handler returns 404 when record missing.` → STE: `The test checks that the handler returns the status code 404 when the record is not in the database.`

**Paradigm guidance**
- Object-Oriented (Java, C#, Python, TypeScript): use an article to separate a class (the type) from an instance (the value): "The `ConnectionPool` class manages a pool of database connections. Each instance keeps a list of open connections." No article directly before a bare identifier: "Call `connect`."
- Functional (Haskell, Elixir, F#, Scala): use an article to separate a type constructor from a value: "The `Ok(value)` pattern shows a successful result. A `Result` value is either `Ok` or `Err`." Write concepts ("immutability," "referential transparency") with no article.
- Procedural (C, Go, Bash): use an article to separate a pointer from the value at the address: "The function receives a pointer to a buffer. The buffer must hold at least 512 bytes."
- Declarative (SQL, Terraform, YAML, Kubernetes): use an article to separate a resource type from a resource instance: "A `Deployment` resource manages a set of pods. The `web` deployment runs three replicas." No article before a named resource: "Apply manifest `web-deployment.yaml`."
- Systems (Rust, C memory, embedded): use an article to make ownership and lifetime relationships clear: "The pointer must point to an initialized region of memory. A borrow of the value must not outlive the owner."

**Edge cases**
- Identifier as a proper noun compared with a concept: `ConnectionPool` alone is a proper noun (no article); "The `ConnectionPool` class" takes "the" because "class" is the noun. "Call `initialize`" takes no article; "The `initialize` function" takes "the" because "function" is the noun.
- "a" compared with "an": use "an" before a vowel sound (an SQL query, an HTML element, an XML parser, an ID, an API key); use "a" before a consonant sound (a URL, a Unix system, a UUID, a JSON payload, a `User` record). Match the usual pronunciation.
- Headings, titles, and table cells: may omit the article; the first sentence below the heading must obey the full rule.
- Product / framework names that start with "The" (e.g. `TheMovieDB`): treat as a proper noun; the leading "The" is part of the identifier, not an article.
- Plural types used as a general statement: "Iterators are lazy in this library" is general (no article); "The iterator stops at the end of the sequence" refers to one identifiable item (uses "the").
- Code samples and command lines: do not add an article inside a code block, command, or log line; this rule applies to prose only.
- Acronyms that expand to a different sound: choose the article for the spoken form (write "an API", not "a API").
- Uncountable technical nouns: "memory," "throughput," "latency," "state" take no indefinite article ("The function allocates memory", not "The function allocates a memory").

**Grammar notes**
- "A" refers to any instance of a type; "the" refers to one specific, identifiable item; no article refers to the type or concept as a whole.
- First mention uses "a" ("The method throws a `ValidationError`"); later mentions use "the" ("The `ValidationError` contains a message field").
- Proper-noun exception: a code identifier is a proper noun — do not put a definite article directly before it ("Call `connect`" correct; "Call the `connect`" not correct).
- Demonstrative adjectives keep their noun: write "this object" or "these headers"; do not write "this" or "these" alone as a pronoun.
- Multi-word nouns: put the article before the full multi-word noun ("the retry policy object", not "retry the policy object").
- Possessive forms replace the article ("its return value" and "the return value of the method" are both correct; do not write "the its return value").

**Checklist**
- [ ] Articles and demonstrative adjectives are used correctly and not removed to shorten text.
- [ ] No article appears before a general statement or an abstract concept.
- [ ] Short sentences use an article before each noun.
- [ ] A long series uses the article only before the first noun, unless an adjective applies to one item only.
- [ ] No definite article appears directly before a code identifier used as a proper noun.
- [ ] "a" and "an" match the spoken sound of the term that follows.
- [ ] Each demonstrative adjective is followed by a noun and refers to one clear topic.

---

<!-- rules-sec5.md -->

# Level 3 — Section 5: Procedural Writing Rules (5.1–5.5)

Scope: how to write procedures in code documentation — README steps, quickstarts,
runbooks, API walkthroughs, docstrings, commit messages, error messages, and CLI help.

Section 5 has five rules:

| Rule | Requirement | One-line test |
| --- | --- | --- |
| 5.1 | Maximum 20 words in a procedural sentence (25 in a note) | Count the words. |
| 5.2 | One instruction per sentence | Count the imperative verbs. |
| 5.3 | Write instructions in the imperative (command) form | Does the sentence start with a base-form verb? |
| 5.4 | Put the condition first, then a comma, then the command | Is the condition before the comma? |
| 5.5 | Notes give information only, never instructions | Can the reader finish the task with the notes removed? |

Counting conventions used throughout Section 5:

- Code blocks, terminal output, and string literals are excluded from word counts.
- A code token inside backticks counts as one word, whatever its length
  (`Result<T, E>` = 1 word; `async fn` = 2 words).
- Hyphenated compounds count as one word (`command-line` = 1 word).
- Numbers, symbols, and parenthetical references count as one word each
  (`(2)` = 1 word; `HTTP/2` = 1 word).
- Procedural sentence: 20-word limit. Descriptive sentence and note: 25-word limit.

---

## Rule 5.1 — Short Sentences (Maximum 20 Words)

> Source: ASD-STE100 Issue 9, Rule 5.1

### Rule

Write short sentences. Use a maximum of 20 words in each procedural sentence.
Warnings and cautions obey the same 20-word limit. Notes (Rule 5.5) may use up
to 25 words per sentence, because notes give information only.

In code documentation, procedures include installation instructions, setup steps,
deployment checklists, debugging workflows, and API usage guides. The reader
executes commands while reading. Long sentences cause skipped actions.

### Apply

- Break a long procedural sentence into shorter sentences. Each sentence covers
  one part of the task.
- Split at the coordinating conjunction. Start the next sentence with
  `Then,`, `Next,`, or `After that,`.
- Move a condition into its own sentence (see Rule 5.4).
- Separate the action from its purpose: instruction first, reason second.
- Convert an enumeration into a bulleted or numbered list. List items are not
  sentences and are not subject to the 20-word limit, but keep them short.

### Examples

> **Non-STE:** Run the database migration script from the project root directory and then restart the application server to apply all pending schema changes to the production environment. (27 words)
>
> **STE:** Run the database migration script from the project root directory. (9 words) Then, restart the application server to apply all pending schema changes. (13 words)

```bash
cd /srv/payments-service
alembic upgrade head
systemctl restart payments.service
```

> **Non-STE:** Set the environment variable HTTP_TIMEOUT to the value 30000 which represents the maximum number of milliseconds that the client will wait for a response from the upstream server. (30 words)
>
> **STE:** Set the environment variable HTTP_TIMEOUT to 30000. (8 words) This value is the maximum wait time in milliseconds for a response from the upstream server. (17 words)

```bash
export HTTP_TIMEOUT=30000
```

> **CAUTION:** IF YOU DELETE THE CONFIGURATION DIRECTORY WITHOUT A BACKUP, YOU CANNOT RESTORE THE APPLICATION SETTINGS TO THEIR PREVIOUS STATE. (18 words)

```bash
cp -r ./config ./config.bak   # back up first
rm -rf ./config               # then delete
```

> **Non-STE:** For more detailed information about the supported authentication methods and their respective configuration parameters in this release, please refer to the official authentication module documentation page. (27 words)
>
> **STE (note, 25-word limit):** For more information about the supported authentication methods, refer to the authentication module documentation. (15 words)

### By document type

**README files.** Installation and quick-start steps. One instruction per step,
each step a command the reader can copy.

> **Non-STE:** Clone the repository to your local machine using the command shown below and then navigate into the newly created project directory before running the setup script. (28 words)
>
> **STE:** Clone the repository to your local machine. (6 words) Then, navigate into the new project directory. (7 words) Run the setup script. (4 words)

```bash
git clone https://github.com/example/payments-service.git
cd payments-service
./setup.sh
```

**API documentation.** Parameter descriptions in tables are descriptive: 25 words.
Setup, authentication, and request-sequencing sentences are procedural: 20 words.

> **Non-STE:** The `page` query parameter accepts a positive integer value that specifies which page of results the server should return in the paginated response to this endpoint. (28 words)
>
> **STE:** The `page` query parameter accepts a positive integer. (8 words) It specifies which page of results to return. (9 words) This is for paginated responses. (6 words)

```http
GET /v1/orders?page=2&page_size=50 HTTP/1.1
Host: api.example.com
Authorization: Bearer ***
```

**Docstrings and inline comments.** Procedural sentences for callers: 20 words.
Return-value and side-effect descriptions: 25 words.

> **Non-STE:** Call this method to initialize the connection pool with the provided configuration and establish the minimum number of idle connections specified in the pool settings before returning control to the caller. (32 words)
>
> **STE:** Call this method to initialize the connection pool. (8 words) Use the provided configuration. (4 words) The method establishes the minimum number of idle connections. (10 words) Then, it returns control to the caller. (8 words)

```python
def init_pool(config: PoolConfig) -> ConnectionPool:
    """Initialize the connection pool.

    Use the provided configuration. The method establishes the minimum
    number of idle connections. Then, it returns control to the caller.
    """
    ...
```

**Commit messages.** Keep the subject line to 72 characters or fewer; this is a
separate constraint from the word count. Body: 20 words for procedural sentences,
25 for descriptive ones.

> **Non-STE:** Refactored the authentication middleware to extract the token validation logic into a separate utility function so that it can be reused by the WebSocket upgrade handler and the GraphQL subscription resolver as well. (35 words)

```text
Refactor authentication middleware

Extracted the token validation logic into a separate utility function.
The WebSocket upgrade handler and the GraphQL subscription resolver now
reuse this function.
```

**Error messages.** Read under stress. Actionable messages: 20 words. Messages that
only report a condition: 25 words. Separate the diagnosis from the remedy.

> **Non-STE:** The configuration file could not be parsed because it contains a syntax error on line 42 that is most likely caused by a missing closing bracket or an unquoted string value containing special characters. (35 words)
>
> **STE:** The configuration file has a syntax error on line 42. (11 words) Check for a missing closing bracket or an unquoted string value. (13 words)

```text
Config error on line 42: missing closing bracket or unquoted string.
```

### By paradigm

**Object-oriented (Java, C++, C#, Python classes).** Do not describe all
constructor parameters in one sentence. Give each parameter its own sentence.

> **Non-STE:** The constructor accepts a database connection string, a logger instance that must implement the ILogger interface, and an optional configuration object for setting the retry policy and the connection timeout duration. (33 words)
>
> **STE:** The constructor accepts three parameters. Parameter one is a database connection string. Parameter two is a logger instance. It must implement the ILogger interface. Parameter three is an optional configuration object. Use this object to set the retry policy and the connection timeout.

```csharp
public DatabaseClient(
    string connectionString,
    ILogger logger,
    ClientConfig? config = null
) { ... }
```

**Functional (Haskell, Elixir, Clojure, Rust).** Give each stage of a composition
pipeline its own sentence, so the reader traces one transformation at a time.

> **Non-STE:** The `process` function first maps the transformation over each element in the list and then filters out any results that are `None` before finally folding the remaining values into a single accumulator using the provided binary operator. (35 words)
>
> **STE:** The `process` function maps a transformation over each element in the list. Then, it filters out any `None` results. Finally, it folds the remaining values into a single accumulator. The provided binary operator controls the fold.

```haskell
process :: (a -> b) -> (b -> Bool) -> (b -> b -> b) -> [a] -> b
process f p op = foldl1 op . filter p . map f
```

**Procedural (C, Go, Bash).** Do not combine an error check with the operation
being checked. Do not describe conditional branching in prose.

> **Non-STE:** Run the configure script to detect your system's available libraries and compiler features and then run make with the -j flag set to the number of CPU cores on your machine to compile the program from source. (37 words)
>
> **STE:** Run the configure script. This script detects your system libraries and compiler features. Then, run make to compile the program from source. Use the -j flag. Set it to the number of CPU cores on your machine.

```bash
./configure
make -j"$(nproc)"
```

**Declarative (SQL, Terraform, Kubernetes YAML).** Do not describe a resource and
all its attributes in one sentence. Check prerequisites before the action.

> **Non-STE:** Execute the migration script against the production database after taking a full backup and verifying that the replication lag on all read replicas is less than five seconds to prevent any data inconsistency during the schema change. (38 words)
>
> **STE:** Take a full backup of the production database. Verify that the replication lag on all read replicas is less than five seconds. Then, execute the migration script against the production database.

```bash
pg_dump "$PROD_DSN" > backup_$(date +%F).sql
REPLICA_LAG=$(psql "$PROD_DSN" -t -c "SELECT EXTRACT(SECONDS FROM now() - pg_last_xact_replay_timestamp());")
[ "$(echo "$REPLICA_LAG < 5" | bc)" -eq 1 ] && alembic upgrade head
```

**Systems (Rust ownership, C memory management).** Never bury a hazard in a
subordinate clause. Prohibition, reason, and consequence each get a sentence.

> **Non-STE:** After calling this function the caller must not use the original buffer pointer because ownership of the memory has been transferred to the callee and any subsequent access through the old pointer will result in undefined behavior. (37 words)
>
> **STE:** After you call this function, do not use the original buffer pointer. Ownership of the memory is transferred to the callee. Access through the old pointer causes undefined behavior.

```rust
fn take_buffer(buf: Vec<u8>) -> Parser {
    // buf is moved into Parser; the caller's buf is no longer valid.
    Parser::new(buf)
}
```

### Edge cases

1. **Long framework or service names.** Use the shortest accepted form on first
   use, define an abbreviation, then use the abbreviation. The abbreviation counts
   as one word. (`Amazon Web Services Elastic Kubernetes Service` → `Amazon EKS`.)
2. **Code keywords that form long phrases.** A backticked token is one word. Do
   not expand generics or type parameters into prose words.
3. **Generated documentation.** Apply the rule to the source docstrings the
   generator reads; the output inherits compliance. Do not edit generated output —
   fix the source. If the source is third-party, apply the 25-word descriptive
   limit and record the exception in the project style guide.
4. **Legal and compliance text.** Not procedural; the 20-word limit does not apply.
   Keep it in a separate "Legal" section or a `NOTE (legal requirement):` block.
5. **Multi-line code examples in prose.** The code block is not counted. The
   introducing sentence and the following sentence each obey the limit
   independently.

### Grammar notes

- A sentence ends with `.`, `?`, or `!`. A comma does not end a sentence.
- Do not join independent clauses with a comma (no comma splices).
- Do not use semicolons to join independent clauses. Use periods.
- Coordinating conjunctions (and, but, or, nor, for, so, yet) may join two short
  clauses only when the total stays at or below 20 words.
  Allowed: `Run the tests and check the output.` (8 words)
- Limit subordinate clause depth to two levels. Flatten deeper structures into
  separate sentences.

> **Non-STE:** The server returns an error when the client sends a request that contains a payload that exceeds the limit that the administrator configured in the settings file. (27 words, 4 levels)
>
> **STE:** The server returns an error when the request payload exceeds the configured limit. The administrator sets this limit in the settings file.

```python
MAX_PAYLOAD = settings["max_payload_bytes"]  # set by the administrator

def handle(req):
    if len(req.body) > MAX_PAYLOAD:
        raise PayloadTooLarge(settings["max_payload_bytes"])
```

### Checklist — Rule 5.1

- [ ] Every procedural sentence has 20 words or fewer.
- [ ] Every note sentence has 25 words or fewer.
- [ ] Warnings and cautions obey the 20-word limit.
- [ ] No comma splices; no semicolons joining independent clauses.
- [ ] Long sentences are split at conjunctions or condition boundaries.
- [ ] Code blocks, terminal output, and string literals are excluded from counts.
- [ ] Backticked code tokens count as one word each.
- [ ] Long technical names are abbreviated after first definition.
- [ ] Generated documentation is fixed at the source level.
- [ ] Subordinate clauses stay within two levels of depth.

> **See also:** Rule 5.2, Rule 5.3, Rule 5.5, Rule 1.1, Rule 1.9, Rule 1.12, Section 8 (word count).

---

## Rule 5.2 — One Instruction Per Sentence

> Source: ASD-STE100 Issue 9, Rule 5.2

### Rule

Write only one instruction in each sentence, unless two or more actions occur at
the same time. Show the sequence of the work steps clearly, usually with numbers
or letters. A procedure may have as many work steps as it needs.

When a sentence carries several instructions, the reader can skip an action. In
code documentation, a skipped action causes a broken configuration, a failed
deployment, or a debugging session that starts from a wrong state.

### Apply

- One instruction for the reader to perform per sentence.
- Use a numbered list to show sequence.
- Join two instructions with "and" only when both actions occur at the same
  moment and cannot be separated.
- You may write more than one sentence in a single work step when:
  - two or more actions occur at the same time and are inseparable, or
  - a result, limit, or measurement follows the action immediately.

Actions that occur at the same time (one sentence is correct):

- Hold the Shift key and click the Reload button.
- Press and release the reset button on the device.
- Copy and replace the existing configuration file.
- Download and extract the archive to the target directory.

### Examples

> **Non-STE:** Open the configuration file in a text editor and locate the database section and change the connection string to point to the staging server and then save the file and close the editor. (37 words, 5 instructions)
>
> **STE:** (1) Open the configuration file in a text editor. (2) Locate the database section. (3) Change the connection string to point to the staging server. (4) Save the file. (5) Close the editor.

```markdown
## Point the app at the staging database

1. Open `config/database.toml` in a text editor.
2. Find the `[database]` section.
3. Set `connection_string = "postgres://staging-db:5432/app"`.
4. Save the file.
5. Close the editor.
```

> **Non-STE:** Run the test suite with the coverage flag enabled and verify that the total line coverage is above 80 percent across all modules in the project. (27 words)
>
> **STE:** Run the test suite with the coverage flag enabled. (9 words) The total line coverage must be more than 80 percent across all project modules. (14 words)
>
> (The second sentence states the result limit. The work step is one action and is not divided.)

```markdown
## Run the tests

Run the suite with coverage:

    pytest --cov=src --cov-report=term-missing

The total line coverage must be more than 80 percent across all project modules.
```

> **Non-STE:** Make sure the environment variable DATABASE_URL is set correctly and then execute the initialization script to create the required database tables and populate them with the seed data. (31 words)
>
> **STE:** Make sure that the environment variable DATABASE_URL is set correctly. Then, execute the initialization script. The script creates the required database tables and populates them with the seed data.
>
> (The check and the execution form one continuous work step. The third sentence describes what the script does.)

```markdown
## Set up the local database

Make sure that the `DATABASE_URL` environment variable is set correctly:

    export DATABASE_URL="postgres://localhost:5432/app"

Then, run the initialization script:

    python scripts/init_db.py

The script creates the required tables and loads the seed data.
```

> **Non-STE:** Set the logging level to debug mode and then restart the application server and after that monitor the log output in the terminal for any error messages that appear during the startup sequence. (35 words)
>
> **STE:** (1) Set the logging level to debug. (2) Restart the application server. (3) Monitor the terminal log output for error messages during the startup sequence.

```markdown
## Debug a slow startup

1. Set the logging level to debug in `config/logging.yaml`.
2. Restart the application server: `systemctl restart app-server`.
3. Watch the log output: `journalctl -u app-server -f`.
```

### By document type

- **README files.** Quick-start sections are the most common violation site.
  Turn each verb into its own numbered step, so the reader can copy one command
  at a time.
- **API documentation.** Split authentication, request construction, and response
  handling into separate steps. Do not fold "get a token" into "call the endpoint".
- **Docstrings.** A usage section is a procedure. One call per sentence. Describe
  the return value in its own sentence.
- **Commit messages.** The body may list several changes, but each sentence
  describes one change. Use a bulleted list when the change has several parts.
- **Error messages.** When a failure has several remedies, give each remedy its
  own sentence, not one chained sentence.

### By paradigm

**Object-oriented.** Instantiation guides, dependency injection setup, and mock
configuration all chain method calls. Give each call its own step.

**Functional.** Do not chain "map, then filter, then fold" as one instruction to
the reader. Document each stage separately.

**Procedural (C, Go, Bash).** Comments in build scripts often compress three
actions into one line.

```bash
# Non-STE
# Download the latest release binary, verify its checksum, and move it to
# /usr/local/bin.

# STE
# Download the latest release binary.
curl -LO https://example.com/tool.tar.gz
# Verify the checksum of the downloaded binary.
sha256sum -c tool.tar.gz.sha256
# Move the binary to /usr/local/bin.
sudo mv tool /usr/local/bin/
```

**Declarative (SQL, Terraform, Kubernetes YAML).** A resource comment that lists
every attribute in one sentence violates the rule.

```hcl
# Non-STE
# Creates an S3 bucket with versioning enabled, a lifecycle policy to
# delete old objects after 30 days, and a private ACL.

# STE
# This resource creates an S3 bucket.
# It enables versioning on the bucket.
# It configures a lifecycle policy to delete objects after 30 days.
# It sets the bucket ACL to private.
```

**Systems (Rust ownership, C memory model).** Allocation, use, and release are
three instructions. Never combine them, because a missed step causes a leak or
undefined behavior.

### Edge cases

1. **A framework CLI command that looks like several instructions.** One command
   the reader runs is one instruction, even when the tool performs many actions
   internally. `npx create-next-app --typescript --eslint` is one step.
2. **Error messages with several root causes.** Give one sentence per cause and
   one sentence per remedy. Do not chain them with "or".
3. **Generated or auto-formatted documentation.** Fix the source comment. The
   generator inherits compliance from its input.
4. **Multi-step test assertions.** A test that asserts several conditions is one
   work step for the reader ("Run the test"), but the documented assertions are
   listed one per line.
5. **Console log messages during a multi-step operation.** Each log line reports
   one completed action. Do not report two actions in one line.

### Grammar notes

**Single predicate rule.** Each imperative sentence has exactly one main verb in
the imperative mood.

- Correct: `Install the package.`
- Incorrect: `Install the package and configure the settings.`

**Simultaneous action exception.** Two predicates may share a sentence when the
actions occur at the same moment. Test: if you can insert a pause between the
actions, they are sequential and must be split.

- Simultaneous (allowed): `Hold the Shift key and click the Reload button.`
- Sequential (split): `Install the package and run the tests.`

**Result clause separation.** Move a result clause introduced by "until", "so
that", "to", or "such that" into its own sentence.

- Before: `Run the migration until the output shows "Migration complete".`
- After: `Run the migration. Continue until the output shows "Migration complete".`
- Before: `Set the timeout to 30 seconds so that the connection does not hang.`
- After: `Set the timeout to 30 seconds. This prevents the connection from hanging.`

**Compound objects are not compound instructions.** One verb with several objects
is one instruction.

- Allowed: `Remove the log files, cache files, and temporary directories.`
- Not allowed: `Remove the log files and restart the server.`

**The "-ing" form prohibition.** Gerund phrases hide implied instructions.

- Before: `After installing the package, configuring the environment, and setting up the database, run the application.`
- After:

```text
(1) Install the package.
(2) Configure the environment.
(3) Set up the database.
(4) Run the application.
```

**Subordinate clauses and instruction count.** If a subordinate clause contains an
action the reader must perform, that action is an instruction and needs its own step.

- Before: `Before you run the tests, set the TEST_MODE environment variable to true.`
- After: `(1) Set the TEST_MODE environment variable to true. (2) Run the tests.`
- Before: `After the build completes, deploy the artifact to the staging server.`
- After: `(1) Wait for the build to complete. (2) Deploy the artifact to the staging server.`

### Checklist — Rule 5.2

- [ ] Each procedural sentence has exactly one imperative verb.
- [ ] Sequences use numbered or lettered steps.
- [ ] "and" joins two verbs only for simultaneous, inseparable actions.
- [ ] Result and limit clauses are separate sentences inside the same step.
- [ ] No gerund phrase hides an instruction.
- [ ] No subordinate clause hides a precondition action.

> **See also:** Rule 5.1, Rule 5.3, Rule 5.5, Rule 1.1, Rule 1.12, Rule 1.13.

---

## Rule 5.3 — Imperative (Command) Form for Instructions

> Source: ASD-STE100 Issue 9, Rule 5.3

### Rule

Write instructions in the imperative (command) form. Start each procedural
instruction with a base-form verb.

Other sentence forms cause ambiguity. The reader cannot tell whether a work step
is required, whether somebody else already did it, or whether the system does it
automatically.

Common imperative verbs in code documentation: run, set, open, save, install,
configure, restart, execute, copy, delete, create, add, enter, select, click,
type, check, build, push, test.

Do not use:

- passive voice (`The file is saved.`)
- gerunds as main verbs (`Saving the configuration before deployment.`)
- modal verbs for instructions (can, could, should, may, might, would)
- indirect phrasing (`It is recommended that you...`, `You are to...`)
- `must` before an imperative in a standard instruction

Reserve `must` for security warnings, data-loss cautions, and safety-critical
conditions.

| Do not write: | Before you remove the cache directory, you must stop the service. |
| --- | --- |
| WRITE: | Before you remove the cache directory, stop the service. |
| STE (safety): | WARNING: IF YOU MUST STORE USER PASSWORDS, ALWAYS HASH THEM WITH BCRYPT. DO NOT STORE PASSWORDS IN PLAIN TEXT. |

### Core examples

> **Non-STE:** The test can be continued.
>
> **STE:** Continue the test.

> **Non-STE:** The old log files are to be removed before the new deployment.
>
> **STE:** Remove the old log files. Then, start the deployment.

> **Non-STE:** The configuration file should be validated against the schema before the application is started.
>
> **STE:** Validate the configuration file against the schema. Then, start the application.

> **Non-STE:** The SSL certificate must be renewed and then the web server must be restarted to apply the changes.
>
> **STE:** Renew the SSL certificate. Then, restart the web server to apply the changes.

> **Non-STE:** It is recommended that you create a backup of the database before running the migration script.
>
> **STE:** Before you run the migration script, create a backup of the database.

### By document type

**README files.** A setup section is instructional; an about section is descriptive.
Do not mix the two moods inside a numbered list.

```markdown
## Setup

1. Install the dependencies with `npm install`.
2. Copy `.env.example` to `.env`.
3. Start the development server with `npm run dev`.
```

**API documentation.** Quickstarts use the imperative. Endpoint behavior is
descriptive: `The endpoint returns a 201 status code.`

**Docstrings and inline comments.** A comment that tells the reader (or the next
maintainer) to act uses the imperative.

```dockerfile
# Build the production Docker image.
docker build -t myapp:prod .
```

**Commit messages.** Write the subject line in the imperative, as an instruction
to the codebase.

```text
# Non-STE commit log
Fixed the login bug
Adding retry logic

# STE commit log (git log --oneline)
Fix the login redirect loop
Add retry logic to the payment client
```

**Error messages.** Describe the failure in the descriptive mood, then give the
recovery step in the imperative.

```text
# Non-STE: a bare, unrecoverable string
ERROR: bad config

# STE: failure, then instruction
Config error on line 42: missing closing bracket. Fix the syntax, then restart the service.
```

### Grammar notes

**Subject omission.** The imperative omits "you". The implied subject is always
the reader, so there is no ambiguity about who acts. Passive constructions hide
the agent. Gerunds function as nouns and describe an action as a concept, not as
a directive.

**Modal verb elimination.** Modals express possibility, permission, or
recommendation. In instructions they create doubt. `You can set the timeout to 30
seconds` reads as optional; `Set the timeout to 30 seconds` does not. `Must` is
redundant before an imperative, because the imperative already conveys necessity.

**Tense consistency.** The imperative uses the base verb form. It does not inflect
for tense, number, or person. This helps translation, machine processing, and
non-native readers.

**Coordination with Rule 5.4.** A descriptive statement may set the context before
the imperative command. Each sentence then has a distinct grammatical role.

```bash
# Descriptive: states a required condition.
# The Docker daemon must be running.
# Imperative: gives the action.
docker build -t myapp:dev .
```

### By paradigm

**Object-oriented.** Setup and configuration use the imperative. Class invariants,
inheritance hierarchies, and design rationale stay descriptive.

> **Non-STE:** An instance of the DatabaseConnection class can be created by calling the static factory method `create`, and you should pass a valid connection string.
>
> **STE:** Create an instance of the `DatabaseConnection` class with the static factory method `create`. Pass a valid connection string.

**Functional.** Project setup, build tool usage, and REPL walkthroughs use the
imperative. Function descriptions stay declarative, because they describe
transformations rather than commands to the reader.

> **Non-STE:** You should apply `map` to transform the list and then you can pipe the result into `filter`.
>
> **STE:** Apply `map` to transform the list. Then, pipe the result into `filter`.

NOTE: When you document a function that the reader must call, the imperative form
is correct. When you document what a function does internally, the descriptive
form is correct.

**Procedural (C, Go, Bash).** Build steps, compile flags, and linking instructions
are all reader actions, so the imperative dominates.

> **Non-STE:** The binary can be compiled with `gcc -O2 -Wall main.c -o tool` and then you are to place it in `/usr/local/bin`.
>
> **STE:** Compile the binary with `gcc -O2 -Wall main.c -o tool`. Then, move the binary to `/usr/local/bin`.

**Declarative (SQL, Terraform, Kubernetes YAML).** The manifest itself is
descriptive: it states desired state. The operator workflow that applies the
manifest is imperative.

```bash
kubectl apply -f deployment.yaml
kubectl rollout status deployment/web
```

**Systems (Rust ownership, C memory management).** Safety instructions use the
imperative and, when the consequence is severe, the `must` form inside a WARNING.

```text
WARNING: DO NOT USE THE BUFFER POINTER AFTER YOU MOVE THE BUFFER.
ACCESS AFTER A MOVE CAUSES UNDEFINED BEHAVIOR.
```

### Extended examples

**Gerund as instruction (Docker docs).**

```text
# Non-STE (reads like a status, not an action)
# Building the image with --no-cache to ensure a clean build.

# STE (direct command the reader runs)
# Build the image with --no-cache to make sure that the build is clean.
docker build --no-cache -t myapp .
```

**Passive voice in a pipeline step (CI/CD docs).** Describe what the pipeline does
in the descriptive mood; give the local runbook in the imperative.

```text
# Descriptive: system behavior
# The CI pipeline runs the test suite after each push to the main branch.

# STE (local runbook for the reader)
# To run the tests locally, run npm test.
```

**"Must" misuse in a standard procedure (database migration).**

```text
# STE (deploy checklist)
Before you deploy to production:
  back up the database
  run the migration script
  notify the on-call engineer
```

**Indirect phrasing in a README (open-source project).**

```markdown
## Contributing

1. Fork the repository.
2. Create a feature branch from `main`.
3. Add tests for your change.
4. Open a pull request.
```

**Conditional imperative in a security-critical context.**

```text
# Non-STE
# When handling user passwords, you should hash them with bcrypt
# and you must never store them in plain text.

# STE
# WARNING: IF YOU MUST STORE USER PASSWORDS, ALWAYS HASH THEM WITH BCRYPT.
# DO NOT STORE PASSWORDS IN PLAIN TEXT. PLAIN-TEXT PASSWORDS CAN CAUSE DATA BREACHES.
```

### Edge cases

1. **A framework name that is also a verb.** `React`, `Express`, `Spring`, `Build`,
   `Watch` are technical code nouns (Rule 1.5) when they name a product. They do
   not turn a descriptive sentence into an instruction.
2. **Generated code and tool output.** Write `--help` text in the imperative at
   the source. Do not post-edit the generated output.
3. **Code keywords that conflict with the rule.** A keyword such as `return`,
   `import`, or `yield` inside backticks is a code token, not the sentence verb.
4. **Release notes and changelogs.** These describe completed work, so they use
   the past or descriptive form, not the imperative. Migration instructions inside
   a release note do use the imperative.
5. **Interactive tutorials and walkthroughs.** Exploratory prompts are acceptable
   in a tutorial. Reference documentation, README files, and API specifications
   follow the rule strictly.

### Checklist — Rule 5.3

- [ ] Every instruction starts with a base-form imperative verb.
- [ ] No passive voice in a procedural sentence.
- [ ] No gerund used as a main verb in an instruction.
- [ ] No modal verb (can, should, may, might) used to give an instruction.
- [ ] `must` appears only in WARNING or CAUTION content, or in a critical condition.
- [ ] Descriptive statements about system behavior stay in the descriptive mood.

> **See also:** Rule 5.1, Rule 5.2, Rule 5.4, Rule 5.5, Rule 1.5, Rule 7.1.

---

<!-- rules-sec6.md -->

# Level 3 — Section 6: Sentence and Paragraph Structure

This slice covers STE-Code Rules 6.1 through 6.6. It is the structural layer of
the standard: how to shape sentences and paragraphs in code documentation so that
a developer can read and understand it on the first pass.

These rules apply to every form of code documentation: README files, API reference
docs, docstrings, inline comments, commit messages, error messages, log entries,
changelogs, and configuration files.

## How to use this slice

- Apply the rules in order 6.1 → 6.2 → 6.3 → 6.4 → 6.5 → 6.6. Each refines the
  output of the previous one.
- 6.1 splits compound thoughts into one subject per sentence.
- 6.2 threads key words through the resulting sentences so they stay connected.
- 6.3 keeps every sentence at 25 words or fewer.
- 6.4 groups related sentences into paragraphs that open with a topic sentence.
- 6.5 keeps each paragraph to a single topic.
- 6.6 keeps each paragraph to six sentences or fewer.

## Rules at a glance

| Rule | One-line requirement | Hard limit |
|------|----------------------|------------|
| 6.1 Give Information Gradually | One subject per sentence; introduce one fact at a time. | No compound multi-subject sentences. |
| 6.2 Use Key Words and Key Phrases | Repeat the key term across sentences; use approved connectors. | Connectors from the approved set only. |
| 6.3 Write Short Sentences | Keep each sentence short and single-idea. | 25 words maximum per sentence. |
| 6.4 Use Paragraphs for Related Info | Group related sentences; open with a topic sentence. | One topic sentence per paragraph. |
| 6.5 One Topic per Paragraph | A paragraph covers exactly one topic. | No topic drift within a paragraph. |
| 6.6 Six Sentences Max per Paragraph | Cap paragraph length to preserve the thread. | 6 sentences maximum per paragraph. |

---

## Rule 6.1 — Give Information Gradually

In code documentation, give information gradually and make sure that each sentence
contains only one subject. If you give too much information too quickly, your
documentation will not be easy to understand, and the reader must read it again.

Give the reader one piece of information at a time. Do not combine multiple
actions, multiple conditions, or multiple subjects in one sentence.

### Core requirement

- One subject per sentence. The subject is the noun phrase that performs the
  action of the main verb.
- One action per sentence where the verbs share that subject. "The function
  validates input and returns a result" is acceptable (one subject, two verbs).
- Two subjects require two sentences: "The function validates input. The
  middleware logs the result." — not "...and the middleware logs..."

### Code-domain example

Non-STE (one dense sentence, multiple subjects and actions):

> The authentication middleware validates bearer tokens from the authorization
> header by calling the `validateToken` function in the security module which
> decodes the JWT payload using the `HS256` algorithm from the `jwt-signer`
> library and checks the `exp` claim against the current server time before
> extracting the `sub` and `role` claims and attaching them as properties on the
> `request.auth` object, and if the token is expired or malformed the middleware
> returns a `401 Unauthorized` response with a JSON error body containing a
> `message` field and an `errorCode` field set to `TOKEN_EXPIRED` or
> `TOKEN_MALFORMED` respectively, while also logging the failure to the audit
> trail via the `AuditLogger.log` static method which writes to the
> `audit_events` table.

STE (one subject, one action per sentence):

> The authentication middleware validates each incoming request. The middleware
> reads the bearer token from the `Authorization` header. It sends the token to
> the `validateToken` function in the `security` module. The `validateToken`
> function decodes the JWT payload. It uses the `HS256` algorithm from the
> `jwt-signer` library. Then it compares the `exp` claim with the current server
> time. If the token is not expired and not malformed, the function gets the
> `sub` and `role` claims. It attaches these claims as properties on the
> `request.auth` object. If the token is expired, the middleware returns a `401
> Unauthorized` response. The response body is a JSON object:
> - The `message` field contains a description of the error.
> - The `errorCode` field is set to `TOKEN_EXPIRED`.
> If the token is malformed, the middleware returns a `401 Unauthorized`
> response. The `errorCode` field in the response is set to `TOKEN_MALFORMED`.
> The middleware also logs each failure to the audit trail. It calls the
> `AuditLogger.log` static method. This method writes a record to the
> `audit_events` table in the primary database. The write uses an asynchronous
> pattern that does not block the response pipeline.

### How it applies by documentation type

- **README.** Introduce one concept per section. Three separate sections for
  purpose, install, and usage — not one paragraph mixing all three.
- **API docs.** Describe the method and path in one sentence; one sentence per
  parameter; one sentence per response field or status code.
- **Docstrings / inline comments.** One behavior per sentence. Each parameter and
  each return condition gets its own sentence.
- **Commit messages.** One logical change per commit. Split a compound change
  into a summary line plus bullet points.
- **Error messages / logs.** One problem per message with a distinct error code.
  One event per log line.
- **Changelogs.** One change per entry; separate feature, fix, and deprecation.

### Paradigm-specific guidance

- **Object-oriented.** Describe one method or one class behavior per sentence.
  For override chains: base class first, then the override, then the side effect.
- **Functional.** Describe one transformation per sentence. A `>>=` or pipe chain
  becomes one sentence per step.
- **Procedural (C, Go, Bash).** One step or one branch per sentence. Do not
  combine an if-else chain, a loop body, and cleanup into one sentence.
- **Declarative (SQL, Terraform, K8s YAML).** One resource, constraint, or column
  per sentence. Do not describe the resource and all its relationships in one
  sentence.
- **Systems (Rust ownership, C memory).** One ownership rule, lifetime, or memory
  operation per sentence. Separate allocation, transfer, annotation, and
  deallocation into distinct sentences.

### Edge cases

- **Framework names with multiple concepts** (e.g. `UserAuthenticationService`):
  treat the whole identifier as one technical noun. Do not split it; apply the
  rule to the surrounding prose.
- **Generated documentation** (OpenAPI, JSDoc, Sphinx): if you cannot change the
  output, add a plain-language summary above it that follows Rule 6.1.
- **Control-flow keywords** (`if`, `else`, `while`, `try/catch`): one sentence
  per branch. Describe the try block and the catch block in separate sentences.
- **Brevity contexts** (CLI `--help`, error codes): use the minimum number of
  sentences, but each must still have one subject. Use fragments only when the
  display format enforces them.
- **Rewriting existing docs:** if a compound sentence hides a dependency, describe
  the dependency first, then the dependent step.

### Connects to

Rule 6.2 (thread the split sentences with key words) · Rule 6.3 (then check the
25-word limit) · Rule 6.4 (group the short sentences into paragraphs) · Rule 6.5
(one topic per resulting paragraph) · Rule 1.1 (use approved words) · Rule 1.11
(one term per concept).

---

## Rule 6.2 — Use Key Words and Key Phrases to Give Your Text a Logical Structure

In code documentation, use key words and key phrases to connect related ideas
across sentences. Key words are terms that occur multiple times to link concepts.
Key phrases are multi-word expressions that serve the same connecting function.

These key words and phrases show how information is related and give the
documentation a logical structure. Do not change them in your text — the same
terminology keeps the documentation clear and correct.

### Approved connecting words and phrases

Use these at the start of a sentence so the reader sees the signal before the
content:

- **Connecting words:** `and`, `but`, `then`, `thus`, `also`, `however`,
  `therefore`.
- **Connecting phrases:** `for example`, `as a result`, `at the same time`.

Do **not** use `moreover`, `furthermore`, `nevertheless`, `subsequently`, or the
verbs `utilize` / `leverage` as connectors — they are not in the approved set.

### Core technique: repeat the key word

Pick the subject of the block (a class name, function name, parameter name,
resource name, or concept such as "middleware") and use it as the key word.

- Repeat it in the subject position of consecutive sentences.
- A pronoun (`it`, `they`) may refer back once, but after two sentences repeat the
  full key word to avoid ambiguity.
- Keep multi-word key phrases intact: "connection pool", "rate limiter",
  "retry policy". Do not shorten them to "pool" mid-documentation.

**Example chain:**

> The authentication middleware validates each incoming request.
> The middleware reads the bearer token from the `Authorization` header.
> It sends the token to the `validateToken` function in the `security` module.
> The `validateToken` function decodes the JWT payload.
> It uses the `HS256` algorithm from the `jwt-signer` library.

"middleware" and "validateToken" recur, so the reader follows the flow.

### How it applies by documentation type

- **README.** Repeat the project name, library name, and core concept across
  sections. Do not switch to "the library" or "this tool" later.
- **API docs.** Use function names, parameter names, and return-type names as key
  words. Consistent key words prevent the reader losing track of which parameter a
  sentence describes.
- **Docstrings.** Introduce the function or class name as the key word in the
  first sentence. Do not switch to synonyms like "transmit", "data", or "queue".
- **Commit messages.** Use the component name and action verb as key phrases. Do
  not switch to "conn pool" or "connection manager" within the same message.
- **Error messages.** Use the operation name and resource name as key words. A
  follow-up message must reuse the resource name, not switch to "document" or
  "path".

**Cross-type consistency:** the same key word must carry the same meaning across
all documentation types in a project (Rule 1.11). If the README says
"authentication middleware", the API docs and docstrings must say the same.

### Paradigm-specific guidance

- **Object-oriented.** Use class names, method names, property names as key words.
  For a method chain, repeat the return type as the key word.
- **Functional.** Use type names, function names, data constructors. The value
  that flows through transformations is the key word.
- **Procedural (C, Go, Bash).** Use variable names, struct fields, error codes.
  Each step must refer to the same variable by the same name.
- **Declarative (SQL, Terraform, K8s YAML).** Use resource names, column names,
  attribute names so the reader maps sentences to exact identifiers.
- **Systems (Rust ownership, C memory).** Use ownership terms, lifetime names,
  pointer names. Precision here prevents bugs.

### Edge cases

- **Framework name conflicts with an unapproved word** (e.g. a library named
  `Leverage`): it is a technical code noun (Rule 1.5). Use it as-is; do not replace
  with an STE synonym.
- **Code keyword too short to be a key word** (Go `go`, Rust `mut`): use a longer
  descriptive key phrase that includes it (e.g. "the `go` keyword starts a
  goroutine" — key word is "goroutine").
- **Generated code** (protobuf, OpenAPI, ORM): use the generated type names as key
  words even if verbose; do not abbreviate.
- **Multi-language repos:** choose one key word for a shared concept (e.g. "map";
  Python `dict`, Java `HashMap`, Go `map`) and note the language-specific names
  once.
- **Multi-word key phrases:** keep the full phrase as the key unit.

### Grammar notes

Rule 6.2 applies *lexical cohesion* to code docs: repetition, pronoun reference,
and approved synonym ties bind sentences into a chain. Keep one stable topic (key
word) in the subject position of every sentence in a block. Connecting words are
grammatical signals placed at the sentence start:

- `and` — addition about the same key word.
- `but` — contrast.
- `then` — next step involving the key word.
- `thus` / `therefore` — consequence.

A **dangling key word** (introduced once, never repeated) breaks the structure.
Repeat the important terms.

### Connects to

Rule 6.1 (the sentences to thread) · Rule 6.3 (short sentences keep key words
visible) · Rule 6.4 (a paragraph is a group of sentences that share a key word) ·
Rule 6.5 (the one topic is the key word) · Rule 1.5 (technical code nouns allowed)
· Rule 1.8 (use standard technical nouns) · Rule 1.9 (prefer short clear nouns) ·
Rule 1.11 (one term per concept).

---

## Rule 6.3 — Write Short Sentences. Use a Maximum of 25 Words in Each Sentence.

Good code documentation uses short sentences for complex topics. Short sentences
give a clear structure and make information easier to understand. In descriptive
code documentation, the maximum sentence length is 25 words.

### Core requirement

- Keep every descriptive sentence at 25 words or fewer.
- A sentence under 25 words can still be too dense if it packs multiple subjects —
  apply Rule 6.1 first, then count words.
- The 25-word limit indirectly limits clause density: a long sentence with several
  clauses overloads working memory.

### Code-domain example

Non-STE (32 words, one sentence):

> The configuration loader reads the YAML manifest file from the filesystem and
> parses it into an in-memory representation that other modules can query at runtime
> to determine their operational parameters.

STE (four sentences, each under 25 words):

> The configuration loader reads the YAML manifest file from the filesystem. It
> parses the file into an in-memory representation. Other modules can query this
> representation at runtime. They use it to find their operational parameters.

### How it applies by documentation type

- **README.** One sentence for the project, one for prerequisites, one for the
  install command. A reader scans and finds each without parsing a dense paragraph.
- **API docs.** One short sentence per part: endpoint, each parameter, each
  response field, each status code.
- **Docstrings.** One sentence for purpose, one per parameter, one for the return
  value, one per exception. Each under 25 words.
- **Commit messages.** Subject line under 72 characters; one short sentence per
  logical change in the body. Makes `git log` and `git bisect` readable.
- **Error messages.** Two short sentences: the problem, then the action. Each
  under 25 words. Log lines stay easy to search.

### Paradigm-specific guidance

- **Object-oriented.** Break inheritance and behavior into separate sentences. A
  class with many methods gets one sentence per method, not one sentence for all.
- **Functional.** Split composition from error behavior: describe the pipeline,
  then the short-circuit, then the error accumulator — each its own sentence.
- **Procedural (C, Go, Bash).** Each step is naturally one sentence. For
  safety-critical detail, split allocation from copy, copy from return.
- **Declarative (SQL, Terraform, K8s YAML).** Document each resource block and
  each argument in its own sentence. Do not mix properties in one 28-word sentence.
- **Systems (Rust ownership, C memory).** Short sentences are essential for memory
  models and concurrency guarantees. Split borrowing, lifetime tracking, and
  compile-time checks into separate sentences.

### Edge cases

- **Long technical terms** (e.g. "single sign-on", "continuous integration and
  continuous deployment"): count the phrase as one word. If it pushes the sentence
  over 25, use the acronym after the first mention.
- **Verbose code keywords** (`synchronized`, `concurrent.futures`,
  `__attribute__((constructor))`): count the keyword as one word, but keep the rest
  short.
- **Compound type signatures** (TypeScript generics, Rust trait bounds): one
  sentence for the type shape, one for the constraints, one for the behavior.
- **Legal / license text** (MIT, Apache, GPL, copyright): exempt from the 25-word
  limit. Surrounding explanation still obeys it.
- **Generated documentation** (JSDoc, Sphinx, `go doc`): the generator may produce
  long sentences; fix the source docstrings, not the generated output.

### Grammar notes

- **Clause density:** most English clauses are 6–12 words. A 25-word sentence holds
  at most two clauses with connecting words — matching working-memory capacity.
- **Coordination vs. subordination:** prefer coordination across separate sentences
  over deep subordination. "The `parse` function throws a `SyntaxError`. This error
  occurs when the input string contains invalid JSON." beats a 27-word sentence with
  three levels of subordination.
- **Implicit connectives:** short sentences in documentation order (purpose → usage →
  edge cases) need no explicit glue; the reader infers the relationship.
- **Counting rules:** count hyphenated compounds as one word ("least-recently-used"
  = 1). Count acronyms as one word (JSON = 1). Count code tokens as one word
  (`Result<Vec<T>>` = 1). Do not count parenthetical word-count notes ("(12
  words)") in examples.

### Connects to

Rule 6.1 (short sentences enable gradual delivery) · Rule 6.2 (short sentences make
key words visible) · Rule 6.4 (short sentences form clear paragraphs) · Rule 6.5
(short sentences help each paragraph stay on topic) · Rule 1.1 (short sentences
reduce the need for complex vocabulary) · Rule 1.10 (short sentences expose jargon).

---

## Rule 6.4 — Use Paragraphs to Show Related Information

In descriptive code documentation, paragraphs keep related information together and
give a logical sequence to the text. A paragraph starts with a **topic sentence**
that tells the developer the topic. The sentences that follow explain or expand it.

When a new paragraph starts, the reader knows there will be a new topic or different
information.

### Core requirement

- Start each paragraph with a topic sentence in the simple present tense, naming the
  topic (a class, function, module, or concept) in subject position.
- Keep related sentences together; use paragraph breaks to separate different
  subjects or different phases of a process.
- Do not start a paragraph with a subordinate clause ("Because...", "When...",
  "If...", "Although..."). Start with the subject.

### Code-domain example

Non-STE (one dense paragraph, mixed topics):

> The data pipeline processes incoming events through a sequence of stages. Each
> stage transforms the event payload and passes it to the next stage. The first
> stage is validation, which checks the event schema and rejects malformed events.
> The second stage is enrichment, which adds metadata such as timestamps, source
> identifiers, and geolocation data from an external lookup service. The third
> stage is transformation, which converts the event into the target format required
> by downstream consumers such as the analytics warehouse and the real-time
> dashboard. The final stage is persistence, which writes the transformed event to
> the primary data store and to the event log for audit purposes. Error handling is
> implemented at each stage to catch exceptions without breaking the entire
> pipeline.

STE (each topic gets its own paragraph with a topic sentence):

> **1. Data Pipeline Overview**
> The data pipeline processes incoming events through a sequence of stages. Each
> stage transforms the event payload and passes it to the next stage. Error
> handling is implemented at each stage to catch exceptions without breaking the
> pipeline.
>
> **2. Validation Stage**
> The first stage is validation. This stage checks the event schema. It rejects
> events that are malformed.
>
> **3. Enrichment Stage**
> The second stage is enrichment. This stage adds metadata to the event:
> - Timestamps
> - Source identifiers
> - Geolocation data from an external lookup service.
>
> **4. Transformation Stage**
> The third stage is transformation. This stage converts the event into the target
> format. Downstream consumers use this format. These consumers include:
> - The analytics warehouse
> - The real-time dashboard.
>
> **5. Persistence Stage**
> The final stage is persistence. This stage writes the transformed event to two
> destinations. It writes the event to the primary data store. It also writes the
> event to the event log for audit purposes.

### How it applies by documentation type

- **README.** Each section starts with a clear topic sentence. Use section headings
  for major topics; paragraph breaks for sub-topics. Move install, configuration,
  and dependencies to separate paragraphs/sections.
- **API docs.** Each endpoint description starts with a topic sentence stating what
  it does. Give authentication, query parameters, response, and status codes
  separate paragraphs (or sub-sections).
- **Docstrings / inline comments.** A docstring starts with a one-line topic
  sentence, then a blank line, then more paragraphs. Each paragraph covers one
  sub-topic (parameters, returns, exceptions, side effects, examples). Inline
  comments are one-sentence paragraphs that state the topic of the following code.
- **Commit messages.** The first line is the topic sentence. The body uses
  paragraphs to group the problem, the changes, and the monitoring notes.
- **Error messages.** Multi-line error output uses paragraphs to separate the error
  description, the diagnostic items, and the stack trace.

### Paradigm-specific guidance

- **Object-oriented.** Separate class purpose, constructor details, public API, and
  internal design into paragraphs. Document each method as a paragraph group.
- **Functional.** Separate the type signature, the behavior, the purity note, and
  the internal composition into paragraphs. Document each pipeline stage separately.
- **Procedural (C, Go, Bash).** Separate initialization, the main loop, cleanup, and
  error handling into paragraphs (phases of execution).
- **Declarative (SQL, Terraform, K8s YAML).** Give each resource or constraint its
  own paragraph group. Separate resource identity, specification, and dependencies.
- **Systems (Rust ownership, C memory).** Separate each ownership relationship or
  memory lifecycle into its own paragraph.

### Edge cases

- **Auto-generated documentation** (JSDoc, Sphinx, `go doc`): insert a blank comment
  line between topics so the generator emits separate paragraphs.
- **Multi-author documents:** apply structural linting. Flag paragraphs over 5
  sentences or lacking a topic sentence. Break long paragraphs at topic boundaries.
- **Cross-cutting concerns** (security, performance): give them their own document or
  top-level section; in each module write a one-paragraph summary with a link.

### Grammar notes

- **Topic sentence as anchor:** the topic sentence carries the main clause; the
  following sentences carry subordinate information. It must be declarative,
  simple present, naming the topic in subject position.
- **Paragraph length:** most STE paragraphs have 2–4 sentences. A paragraph over 5
  sentences usually covers more than one topic — split it.
- **Paragraph breaks as signals:** place a break before a new concept, a code
  example, a warning, a list, or a change in abstraction level. Do not break between
  a topic sentence and its supporting sentences.
- In markdown, separate paragraphs with a blank line (not indentation alone).

### Connects to

Rule 6.1 (paragraphs implement the gradual sequence at section level) · Rule 6.2
(topic sentences use key words) · Rule 6.3 (short sentences make paragraphs
readable) · Rule 6.5 (one paragraph, one topic) · Rule 1.1 (topic sentences use
approved words) · Rule 1.5 (technical nouns allowed in topic sentences) · Rule 1.11
(one term per concept across paragraphs) · Rule 7.1 (use lists for three or more
items).

---

## Rule 6.5 — Make Sure That Each Paragraph Has Only One Topic

In descriptive code documentation, paragraphs describe topics, and each paragraph
must have only one topic. The topic sentence is the first and most important
sentence in a paragraph. The other sentences add more information on that topic.

If you write down the topic sentences of a text, you get a good outline of its
content. The reader finds applicable information quickly.

### Core requirement

- One paragraph = one topic. The topic sentence names that topic.
- A paragraph that covers two topics must be split, even if it is short.
- The topic sentence usually contains a key word (Rule 6.2) and/or a connecting word
  (Rule 6.2) to link to the previous paragraph.
- Use deductive structure: the topic sentence is first, never last (developers scan).

### Code-domain example

Non-STE (five topics in one sentence):

> The authentication middleware validates each request and the logging system records
> all validation failures to the audit trail while the response pipeline returns JSON
> error bodies with error codes and the database connection pool maintains idle
> connections for reuse and the configuration module reloads settings when the
> manifest file changes on disk.

STE (three single-topic paragraphs; reading only the topic sentences gives the
outline):

> The authentication middleware validates each incoming request. The middleware reads
> the bearer token from the `Authorization` header. It sends the token to the
> `validateToken` function in the `security` module. The `validateToken` function
> decodes the JWT payload using the `HS256` algorithm from the `jwt-signer` library.
> Then it compares the `exp` claim with the current server time. If the token is not
> expired and not malformed, the function gets the `sub` and `role` claims and
> attaches them to the `request.auth` object.
>
> If the token is expired, the middleware returns a `401 Unauthorized` response. The
> response body is a JSON object with a `message` field and an `errorCode` field set
> to `TOKEN_EXPIRED`. If the token is malformed, the middleware returns a `401
> Unauthorized` response with the `errorCode` field set to `TOKEN_MALFORMED`.
>
> The middleware also logs each failure to the audit trail. It calls the
> `AuditLogger.log` static method. This method writes a record to the `audit_events`
> table in the primary database. The write uses an asynchronous pattern that does not
> block the response pipeline.

Outline from topic sentences: (1) "The authentication middleware validates each
incoming request." (2) "If the token is expired, the middleware returns a `401
Unauthorized` response." (3) "The middleware also logs each failure to the audit
trail."

### How it applies by documentation type

- **README.** One topic per section: "Installation" explains install only, not API
  design; "Configuration" shows config only, not usage.
- **API docs.** One paragraph per aspect: endpoint purpose, request format, each
  response status group, authentication. Do not mix `200 OK` with `404 Not Found`.
- **Docstrings / inline comments.** The docstring topic is the function's contract:
  inputs, outputs, behavior. Do not explain why it exists or list its callers.
- **Commit messages.** One commit = one topic. Two unrelated changes belong in two
  commits. The subject line summarizes the single topic; the body expands only on it.
- **Error messages.** One topic: what went wrong (one sentence), why (one sentence),
  how to fix (one sentence). No stack traces or unrelated state in the message body.

### Paradigm-specific guidance

- **Object-oriented.** One paragraph per concern: class purpose, constructor,
  public interface, inheritance, thread safety. Method implementation details go in
  the method docstring.
- **Functional.** One paragraph per transformation: input shape, transformation
  logic, output shape, edge cases. Document each pipeline stage separately.
- **Procedural (C, Go, Bash).** One paragraph per phase: initialization, main loop,
  cleanup, error handling. Do not merge `setup` with `teardown`.
- **Declarative (SQL, Terraform, K8s YAML).** One paragraph per table/view,
  resource block, or object. A Deployment and its Service are separate topics even
  though they work together.
- **Systems (Rust ownership, C memory).** One paragraph per ownership relationship or
  memory lifecycle. Allocation and deallocation share a paragraph only when they are
  one lifecycle (e.g. RAII).

### Edge cases

- **Framework names that are unapproved words** (e.g. a library named `Execute`):
  technical code noun (Rule 1.5), allowed. But do not use it as a verb in the same
  paragraph — write "Use the `Execute` library to run jobs", not "Execute jobs with
  `Execute`".
- **Large multi-topic functions:** list responsibilities as bullet points in the
  docstring; give each its own paragraph in module-level docs. The docstring is a
  topic index.
- **Generated documentation:** each individual docstring must still be a self-contained
  topic even though the page combines many.
- **Cross-cutting concerns:** give them their own document/section; in each module
  write a one-paragraph summary with a link.
- **Error-code reference tables:** the table is the container; each descriptive cell
  is a mini-paragraph that covers one error condition.

### Grammar notes

- **Topic sentence position:** always first (deductive). A topic sentence at the end
  is invisible to a scanning reader.
- **Key word repetition:** the topic sentence introduces a key word; supporting
  sentences repeat it or use a clear synonym. A new key word without connection means
  the paragraph has drifted.
- **Connecting words in the topic sentence:** "Also," (more on same topic), "However,"
  (contrast), "For example," (instance), "Therefore," (result).
- **Paragraph length:** 3–7 sentences. A 10+ sentence paragraph almost always has more
  than one topic.
- **Visual separation:** in markdown, separate paragraphs with a blank line; screen
  readers and renderers do not treat indentation as a break.

### Connects to

Rule 6.1 (gradual information) · Rule 6.2 (key words in topic sentences) · Rule 6.3
(short sentences make topic drift visible) · Rule 6.4 (paragraphs group related
info) · Rule 1.11 (consistent terms prevent false topic starts) · Rule 3.6 (topic
sentence usually starts with a simple-present verb) · Rule 5.1 (imperative procedural
paragraphs) · Rule 6.6 (six-sentence cap).

---

## Rule 6.6 — Make Sure That No Paragraph Has More Than Six Sentences

In code documentation, make sure that no paragraph has more than six sentences.
Paragraphs divide a documentation block into logical units and keep the developer's
attention. If a paragraph is too long, it cannot do this. Do not put different
topics in the same paragraph (see Rule 6.5). If a paragraph has more than six
sentences, divide it into two smaller paragraphs.

### Core requirement

- Cap each paragraph at six sentences. This is a ceiling, not a target — most good
  paragraphs use two to four sentences.
- Rule 6.6 works with 6.4 (use paragraphs) and 6.5 (one topic): 6.4 says use
  paragraphs, 6.5 says one topic each, 6.6 says keep them short.
- Split a paragraph when: it has more than six sentences, OR it covers two or more
  topics (Rule 6.5), OR a sentence introduces a new key word not used earlier (Rule
  6.2).

### Code-domain example

Non-STE (four components in one five-sentence paragraph):

> The connection pool manager has these primary components: a set of pre-allocated
> socket connections that the manager reuses across requests to avoid repeated TCP
> handshakes and TLS negotiation, a background reaper thread that closes idle
> connections and runs a periodic health probe, a bounded queue that holds pending
> acquire requests and rejects with a timeout error, and a metrics collector that
> records active connections and wait-time distribution for observability.

STE (one outline paragraph plus four short paragraphs, each under six sentences):

> The connection pool manager has these primary parts:
> - A set of pre-allocated socket connections.
> - A background reaper thread.
> - A bounded queue for pending acquire requests.
> - A metrics collector.
>
> The socket connections let the application reuse one link for many requests. The
> reuse avoids repeated TCP handshakes and TLS negotiation.
>
> The reaper thread closes connections idle longer than the idle timeout. The reaper
> thread also runs a periodic health probe to find dropped links.
>
> The bounded queue holds pending acquire requests when all connections are in use.
> The queue rejects new requests with a timeout error after the acquire timeout
> expires.
>
> The metrics collector records the number of active connections. The collector also
> records the wait-time distribution and the count of rejected acquires. The
> observability stack reads these metrics.

### How it applies by documentation type

- **README.** One feature = one short paragraph. A feature paragraph listing install,
  configure, and usage in eight sentences forces three topics at once — split them.
- **API docs.** One short paragraph per aspect: purpose, request, response, errors.
- **Docstrings.** Keep the summary paragraph short. One short paragraph per concern;
  move a long parameter list to a bulleted list and keep the prose under six
  sentences.
- **Error messages / logs.** An error message is usually one sentence; keep a
  multi-line diagnostic block to six lines or fewer, or split into a cause paragraph
  and a recovery paragraph.

### Paradigm-specific guidance

- **Object-oriented.** One responsibility per paragraph. Each collaborator of a class
  gets its own short paragraph.
- **Functional.** One transformation stage per paragraph; a map/filter/fold pipeline
  should not live in one paragraph.
- **Procedural (C, Go, Bash).** One phase per paragraph: setup, execution, cleanup.
  Do not document `setup` and `teardown` together.
- **Declarative (SQL, Terraform, K8s YAML).** One resource or block per paragraph; a
  module declaring a database, a cache, and a queue documents each separately.
- **Systems (Rust ownership, C memory).** One ownership rule per paragraph; memory
  contracts are easy to bury in a long paragraph.

### Edge cases

- **A topic needs more than six sentences:** keep the first paragraph under six
  sentences and continue the same topic in a second paragraph. Start the second with a
  connecting phrase ("Also,", "In addition,") so the reader knows the topic continues.
- **A list counts as one paragraph:** a bulleted/numbered list is one paragraph
  regardless of item count. Rule 6.6 limits the prose around it, not the list items.
  Keep the introductory sentence short; do not add a long closing sentence.
- **Generated docs that emit long paragraphs:** set the generator to break at sentence
  boundaries if you can. If you cannot, add a short human-written summary above the
  generated block; the summary must follow Rule 6.6. The generated block is exempt only
  if you do not edit its source annotations.
- **A short paragraph that mixes two topics:** Rule 6.6 and 6.5 are independent. A
  three-sentence paragraph describing both the cache and the queue must split even
  though it is under the sentence limit.

### Grammar notes

- **Why six:** a reader holds a paragraph's topic in working memory; after about six
  sentences the topic fades and they must re-read. The limit guards against drift.
- **Sentence count, not word count:** six short sentences or six long sentences both
  pass. Prefer two to four short sentences; apply Rule 6.3 together with 6.6.
- **Lists and tables reset the count:** the surrounding prose (introductory + closing
  sentence) is what counts. Keep that prose under six sentences.
- **Splitting technique:** split where the key word changes (Rule 6.2) or the topic
  changes (Rule 6.5). Start the new paragraph with a topic sentence naming the new key
  word.
- **Procedures:** each step is its own paragraph by convention, so 6.6 rarely applies;
  it applies when a step has a long note — keep the note under six sentences.

### Connects to

Rule 6.4 (6.6 is the size limit 6.4 assumes) · Rule 6.5 (6.6 limits sentence count,
6.5 limits topic count) · Rule 6.1 (short paragraphs support gradual delivery) · Rule
6.2 (the new paragraph starts with the new key word) · Rule 6.3 (short sentences make
it easier to stay under six).

---

## Applying Section 6 end to end (the pipeline)

When writing or checking documentation, apply the rules in sequence:

1. **6.1** — Split compound sentences so each has one subject and one action.
2. **6.2** — Thread the split sentences with repeated key words and approved connectors.
3. **6.3** — Check every sentence is 25 words or fewer.
4. **6.4** — Group related sentences into paragraphs opened by a topic sentence.
5. **6.5** — Verify each paragraph covers exactly one topic; split if it drifts.
6. **6.6** — Verify each paragraph has six sentences or fewer; split if longer.

A paragraph that passes 6.4, 6.5, and 6.6 is short, single-topic, and scannable. This
is the structural backbone that the vocabulary rules (Section 1) and the writing rules
(Sections 3, 5, 7) build on.

### Related rules outside Section 6

- Rule 1.1 — Use approved words from the STE-Code dictionary.
- Rule 1.5 — Technical code nouns are allowed.
- Rule 1.8 / 1.9 — Use standard, short, clear technical nouns as key words.
- Rule 1.10 — No slang, jargon, or regional terms.
- Rule 1.11 — One term per concept (keeps key words and topics stable).
- Rule 3.6 — Use approved forms of verbs.
- Rule 5.1 — Write instructions in the imperative mood.
- Rule 7.1 — Use lists for three or more items.

---

<!-- rules-sec7.md -->

# Level 3 — Section 7: Safety Instructions (Warnings and Cautions)

This slice covers STE-Code Rules 7.1, 7.2, and 7.3. It is the risk layer of the
standard: how to signal risk, how to open a safety instruction, and how to
explain what happens if the reader ignores it.

These rules apply to every form of code documentation: README files, API
reference docs, docstrings, inline comments, commit messages, error messages,
changelogs, release notes, and configuration files.

## How to use this slice

- Apply the rules in order 7.1 → 7.2 → 7.3. Each adds one required part of a
  complete safety instruction.
- 7.1 picks the signal word (WARNING or CAUTION) that matches the risk level.
- 7.2 opens the body with a clear command or a clear condition.
- 7.3 states the consequence, so the reader knows why the instruction matters.

A safety instruction is complete only when it has all three parts:

```
WARNING: [COMMAND OR CONDITION]. [CONSEQUENCE]. [RISK ESCALATION].
```

If the command is missing, the instruction is not actionable. If the consequence
is missing, the reader does not know why the command matters. Both are required.

## Rules at a glance

| Rule | One-line requirement | Hard limit |
|------|----------------------|------------|
| 7.1 Identify the level of risk | Use WARNING or CAUTION as the first word; match it to the real risk. | One signal word per instruction. |
| 7.2 Start with a command or condition | The first sentence after the colon is a command or a condition. | 20 words maximum for that sentence. |
| 7.3 Explain the risk | Name the concrete consequence in cause-first order. | No vague nouns ("problems," "issues"). |

## Risk level mapping

| Risk in the code domain | Signal word | Release-note severity |
|-------------------------|-------------|-----------------------|
| Security vulnerability, data loss, system corruption | WARNING | BREAKING |
| Unexpected behavior, performance degradation, incorrect results | CAUTION | DEPRECATED |
| Information only, no risk | NOTE | NOTE |

If two levels of risk apply together, use WARNING.

---

## Rule 7.1 — Use an Applicable Word to Identify the Level of Risk

> Adapted from ASD-STE100 Issue 9, Rule 7.1.

In code documentation, use a signal word (for example, WARNING or CAUTION) to
immediately show your reader the level of the related risk.

- If there is a risk of security vulnerabilities, data loss, or system
  corruption, use a WARNING.
- If there is a risk of unexpected behavior, performance degradation, or
  incorrect results, use a CAUTION.
- If the two levels of risk apply together, use a WARNING.

Do not let the signal word become routine noise. A document that marks every
note as a WARNING teaches the reader to ignore all of them.

### Escalation: choose the level from the real risk, not from the topic

An abstract caution must become a warning when the true risk is security or data
loss. This is the core move of the rule.

> **Non-STE:** CAUTION: ALWAYS VALIDATE INPUT DATA.
>
> **STE:** WARNING: BEFORE YOU PROCESS INPUT DATA, MAKE SURE THAT YOU SANITIZE AND VALIDATE THE DATA. UNSANITIZED INPUT CAN CAUSE SECURITY BREACHES AND DATA LOSS.

> **Non-STE:** CAUTION: THE CONFIGURATION FILE MAY CONTAIN OUTDATED SETTINGS.
>
> **STE:** CAUTION: BEFORE YOU DEPLOY THE APPLICATION, COMPARE THE CONFIGURATION FILE AGAINST THE REFERENCE CONFIGURATION. OUTDATED SETTINGS CAN CAUSE UNEXPECTED BEHAVIOR AND INCORRECT RESULTS.

The first pair escalates to WARNING because the true risk is a security breach.
The second stays a CAUTION because the risk is incorrect results only.

### By documentation type

| Type | Use WARNING for | Use CAUTION for |
|------|-----------------|-----------------|
| README | Security-critical setup steps | Configuration that can cause incorrect behavior |
| API docs | Sensitive data, authentication, destructive endpoints | Side effects, rate limits |
| Docstrings and comments | Misuse that corrupts data or breaks security | Performance pitfalls, non-obvious side effects |
| Commit messages | Security fixes, data-loss prevention | Behavior changes downstream consumers must know |
| Error messages | Detected security compromise or data corruption | Detected condition that gives incorrect results |

**README — WARNING:**

> **Non-STE:** Note: you should be careful with the API key and not commit it to version control.
>
> **STE:** WARNING: DO NOT COMMIT THE API KEY TO VERSION CONTROL. AN EXPOSED API KEY CAN CAUSE UNAUTHORIZED ACCESS AND DATA LOSS.

**README — CAUTION:**

> **Non-STE:** Make sure the port number does not conflict with other services or the app won't start.
>
> **STE:** CAUTION: BEFORE YOU START THE APPLICATION, CHECK THAT THE PORT NUMBER DOES NOT CONFLICT WITH OTHER SERVICES. A PORT CONFLICT CAN CAUSE THE APPLICATION TO FAIL.

**API docs — WARNING for a destructive endpoint:**

> **Non-STE:** DELETE /users/:id removes the user and all associated data, this cannot be undone.
>
> **STE:** WARNING: `DELETE /users/:id` REMOVES THE USER AND ALL RELATED DATA PERMANENTLY. THIS OPERATION CANNOT BE UNDONE. VERIFY THE USER ID BEFORE YOU SEND THE REQUEST.

**API docs — CAUTION for a rate limit:**

> **Non-STE:** This endpoint allows 100 requests per minute, exceeding this will return 429 errors.
>
> **STE:** CAUTION: THE ENDPOINT ALLOWS A MAXIMUM OF 100 REQUESTS PER MINUTE. IF YOU EXCEED THE LIMIT, THE ENDPOINT RETURNS A 429 ERROR. MONITOR THE `X-RateLimit-Remaining` HEADER.

**Docstring — WARNING (Python):**

```python
def execute_sql(query: str, params: tuple = ()) -> list:
    """Run a raw SQL query.

    WARNING: THIS FUNCTION EXECUTES THE QUERY DIRECTLY. SANITIZE ALL
    USER INPUT BEFORE YOU PASS IT TO THIS FUNCTION. UNSANITIZED INPUT
    CAN CAUSE SQL INJECTION ATTACKS AND DATA LOSS.

    Parameters:
        query: The raw SQL query string.
        params: The query parameters. The default is an empty tuple.

    Returns:
        A list of result rows.
    """
```

**JSDoc — CAUTION (JavaScript):**

```javascript
/**
 * Caches the result of an expensive computation.
 *
 * CAUTION: THE CACHE USES MEMORY PROPORTIONAL TO THE NUMBER OF
 * UNIQUE ARGUMENTS. FOR UNBOUNDED INPUT SETS, USE A CACHE WITH
 * A SIZE LIMIT. AN UNLIMITED CACHE CAN CAUSE MEMORY EXHAUSTION.
 *
 * @param {Function} fn - The function to cache.
 * @returns {Function} A cached version of the function.
 */
function memoize(fn) {
  const cache = new Map();
  return function (...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}
```

**Commit messages.** Use `WARNING:` as the type prefix for commits that fix
security vulnerabilities or prevent data loss. Use `CAUTION:` for commits that
change behavior downstream consumers depend on. Changelog tools can then group
commits by severity.

> **Non-STE:** fix: patch SQL injection in login form
>
> **STE:** WARNING: Prevent SQL injection in the login form. The previous code did not sanitize the `username` parameter. This vulnerability could permit unauthorized database access.

> **Non-STE:** change: update default timeout from 30s to 10s
>
> **STE:** CAUTION: Change the default timeout from 30 seconds to 10 seconds. Update all callers that rely on the previous default. The shorter timeout can cause connection failures in high-latency environments.

**Error messages.** Error messages are read during incidents. They must be
actionable.

> **Non-STE:** Error: invalid signature
>
> **STE:** WARNING: THE REQUEST SIGNATURE IS NOT VALID. THE REQUEST MAY HAVE BEEN TAMPERED WITH. REJECT THE REQUEST. CHECK YOUR SIGNING KEY AND ALGORITHM.

> **Non-STE:** The configuration value for max_connections must be less than database pool size.
>
> **STE:** CAUTION: THE `max_connections` VALUE IS GREATER THAN THE `pool_size` VALUE. THIS CONFIGURATION CAN CAUSE CONNECTION FAILURES. SET `max_connections` TO A VALUE THAT IS NOT MORE THAN `pool_size`.

### Paradigm notes for 7.1

| Paradigm | WARNING when | CAUTION when |
|----------|--------------|--------------|
| Object-oriented (Java, C++, C#, Python classes) | A subclass override can break a security invariant | A method mutates shared state |
| Functional (Haskell, Elixir, Clojure, Rust) | An unsafe escape hatch breaks referential transparency | A lazy operation can cause a space leak |
| Procedural (C, Go, Bash) | Buffer overflow, use-after-free, undefined behavior | Platform-specific behavior, resource limits |
| Declarative (SQL, Terraform, Kubernetes YAML) | Data destruction, public exposure of a resource | Configuration values with subtle effects |
| Systems (Rust ownership, C memory) | Undefined behavior, data races, memory corruption | Performance characteristics of unsafe optimizations |

**Object-oriented — WARNING (Java):**

> **Non-STE:** Subclasses should be careful to call super.validate() before performing custom validation.
>
> **STE:** WARNING: OVERRIDE THE `validate` METHOD WITH CARE. CALL `super.validate()` BEFORE YOU ADD CUSTOM VALIDATION LOGIC. IF YOU SKIP THE BASE VALIDATION, UNTRUSTED DATA CAN BYPASS SECURITY CHECKS.

```java
abstract class RequestValidator {
    /** Base security checks that apply to all request types. */
    void validate(Request request) {
        if (request.getUser() == null) {
            throw new SecurityException("Missing user context");
        }
        if (!request.isAuthenticated()) {
            throw new SecurityException("Request is not authenticated");
        }
    }
}

class PaymentRequestValidator extends RequestValidator {
    @Override
    void validate(Request request) {
        // WARNING: CALL super.validate() BEFORE YOU ADD CUSTOM LOGIC.
        super.validate(request);
        PaymentRequest payment = (PaymentRequest) request;
        if (payment.getAmount() <= 0) {
            throw new IllegalArgumentException("Amount must be greater than zero");
        }
    }
}
```

**Object-oriented — CAUTION (C++ shared state):**

> **Non-STE:** Note that this method modifies the internal cache which may affect other threads.
>
> **STE:** CAUTION: THE `invalidateCache` METHOD MODIFIES THE INTERNAL CACHE. THIS CHANGE AFFECTS ALL THREADS THAT USE THE CACHE. USE A LOCK BEFORE YOU CALL THIS METHOD.

**Functional — WARNING and CAUTION (Haskell):**

> **Non-STE:** Use unsafePerformIO with caution as it breaks purity.
>
> **STE:** WARNING: `unsafePerformIO` BYPASSES THE IO TYPE SYSTEM. THIS FUNCTION HIDES SIDE EFFECTS IN PURE CODE. INCORRECT USE CAN CAUSE NONDETERMINISTIC BEHAVIOR AND DATA CORRUPTION. USE THIS FUNCTION ONLY WHEN NO SAFE ALTERNATIVE EXISTS.

> **Non-STE:** foldl is strict, but if you accumulate large thunks you might run out of memory.
>
> **STE:** CAUTION: `foldl` ACCUMULATES UNEVALUATED EXPRESSIONS (THUNKS). A LARGE ACCUMULATOR CAN CAUSE A SPACE LEAK AND MEMORY EXHAUSTION. USE `foldl'` FOR STRICT ACCUMULATION.

**Procedural — WARNING (C) and CAUTION (Go):**

> **Non-STE:** Make sure the destination buffer is at least as large as the source string when using strcpy.
>
> **STE:** WARNING: `strcpy` DOES NOT CHECK THE SIZE OF THE DESTINATION BUFFER. IF THE SOURCE STRING IS LARGER THAN THE DESTINATION BUFFER, THE FUNCTION WRITES PAST THE BUFFER BOUNDARY. THIS BUFFER OVERFLOW CAN CAUSE SECURITY VULNERABILITIES AND SYSTEM CRASHES. USE `strncpy` WITH A SIZE LIMIT.

> **Non-STE:** On Windows, filepath separator is backslash, be careful with cross-platform paths.
>
> **STE:** CAUTION: THE `filepath` PACKAGE USES THE OPERATING SYSTEM PATH SEPARATOR. USE `filepath.Join` OR `filepath.FromSlash` TO BUILD CROSS-PLATFORM PATHS. HARDCODED SEPARATORS CAUSE INCORRECT PATHS.

**Declarative — WARNING (SQL), CAUTION (Terraform), WARNING (Kubernetes):**

> **Non-STE:** Caution: this migration drops the users table.
>
> **STE:** WARNING: THIS MIGRATION DROPS THE `users` TABLE. ALL USER DATA IS DELETED PERMANENTLY. BACK UP THE DATABASE BEFORE YOU RUN THIS MIGRATION. VERIFY THAT YOU RUN THE MIGRATION AGAINST THE CORRECT DATABASE.

> **Non-STE:** Changing the subnet_id will cause the EC2 instance to be recreated, which may cause downtime.
>
> **STE:** CAUTION: IF YOU CHANGE THE `subnet_id` ARGUMENT, TERRAFORM DESTROYS THE EXISTING INSTANCE AND CREATES A NEW ONE. THIS RECREATION CAUSES DOWNTIME. THE INSTANCE PUBLIC IP ADDRESS CHANGES. PLAN THE CHANGE DURING A MAINTENANCE WINDOW.

> **Non-STE:** Be careful with LoadBalancer type services as they expose your app to the internet.
>
> **STE:** WARNING: A SERVICE OF TYPE `LoadBalancer` EXPOSES THE APPLICATION TO THE PUBLIC INTERNET. UNAUTHORIZED USERS CAN SEND REQUESTS TO THE APPLICATION. MAKE SURE THAT AUTHENTICATION AND NETWORK POLICIES ARE IN PLACE BEFORE YOU APPLY THIS CONFIGURATION.

**Systems — WARNING and CAUTION (Rust):**

> **Non-STE:** Dereferencing a raw pointer is unsafe and may cause undefined behavior if the pointer is invalid.
>
> **STE:** WARNING: DEREFERENCING A RAW POINTER CAN CAUSE UNDEFINED BEHAVIOR. UNDEFINED BEHAVIOR CAN CORRUPT MEMORY, CAUSE SECURITY VULNERABILITIES, AND CRASH THE PROGRAM. BEFORE YOU DEREFERENCE A RAW POINTER, CHECK THAT: (1) THE POINTER IS NOT NULL. (2) THE POINTER IS CORRECTLY ALIGNED. (3) THE POINTER POINTS TO VALID, INITIALIZED MEMORY.

> **Non-STE:** Using MaybeUninit can improve performance but be careful about initialization.
>
> **STE:** CAUTION: `MaybeUninit` SKIPS INITIALIZATION TO IMPROVE PERFORMANCE. IF YOU READ UNINITIALIZED MEMORY, THE PROGRAM BEHAVIOR IS UNDEFINED. MAKE SURE THAT YOU INITIALIZE THE VALUE BEFORE YOU READ IT. MEASURE THE PERFORMANCE GAIN BEFORE YOU USE THIS TYPE.

### Common signal-word failures

| Failure | Fix |
|---------|-----|
| CAUTION used for a security risk (exposed API key) | Escalate to WARNING; name unauthorized access, data theft, service abuse |
| WARNING with no consequence ("run this migration carefully") | Name the irrecoverable loss and give a pre-action check |
| Abstract caution ("be mindful of thread safety") | Name the class, the race, and the safe alternative |
| WARNING used for slowness | Downgrade to CAUTION; give the complexity, a threshold, and an alternative |
| No signal word at all | Add the signal word that matches the real risk |
| Two risks in one callout, marked CAUTION | If either risk is WARNING-level, use WARNING |

Worked corrections:

> **Non-STE:** CAUTION: Store the API key in an environment variable.
>
> **STE:** WARNING: STORE THE API KEY IN AN ENVIRONMENT VARIABLE. DO NOT HARDCODE THE API KEY IN THE SOURCE CODE. AN EXPOSED API KEY CAN CAUSE UNAUTHORIZED ACCESS, DATA THEFT, AND SERVICE ABUSE. ADD THE `.env` FILE TO `.gitignore`.

> **Non-STE:** WARNING: Run this migration carefully.
>
> **STE:** WARNING: BEFORE YOU RUN THIS MIGRATION, BACK UP THE `transactions` TABLE. THE MIGRATION REMOVES ALL RECORDS OLDER THAN 90 DAYS. THE DATA CANNOT BE RECOVERED AFTER THE MIGRATION COMPLETES. VERIFY THE DATE THRESHOLD AGAINST YOUR RETENTION POLICY.

> **Non-STE:** CAUTION: Be mindful of thread safety when using this library.
>
> **STE:** CAUTION: THE `Cache` CLASS IS NOT THREAD-SAFE. IF YOU SHARE A `Cache` INSTANCE ACROSS THREADS, RACE CONDITIONS CAN CAUSE INCORRECT CACHE ENTRIES AND APPLICATION CRASHES. USE `ConcurrentCache` FOR MULTI-THREADED APPLICATIONS. USE A MUTEX FOR MANUAL SYNCHRONIZATION.

> **Non-STE:** WARNING: This function is slow for large inputs.
>
> **STE:** CAUTION: THIS FUNCTION HAS O(N²) TIME COMPLEXITY. FOR INPUTS LARGER THAN 10,000 ITEMS, THE FUNCTION CAN TAKE SEVERAL MINUTES TO COMPLETE. USE `fastSort` FOR LARGE INPUTS. `fastSort` HAS O(N LOG N) TIME COMPLEXITY.

> **Non-STE:** The DEBUG_MODE environment variable controls verbose logging. Setting it to true in production will leak sensitive information.
>
> **STE:** WARNING: DO NOT SET `DEBUG_MODE=true` IN A PRODUCTION ENVIRONMENT. DEBUG MODE WRITES SENSITIVE DATA TO THE LOG OUTPUT. THIS DATA INCLUDES REQUEST BODIES, AUTHENTICATION TOKENS, AND DATABASE QUERIES. AN ATTACKER WITH LOG ACCESS CAN STEAL USER CREDENTIALS.

> **Non-STE:** CAUTION: The reset method clears the database and disables authentication, only use in development.
>
> **STE:** WARNING: THE `reset` METHOD CLEARS THE DATABASE AND DISABLES AUTHENTICATION. IF YOU CALL THIS METHOD IN A PRODUCTION ENVIRONMENT, ALL USER DATA IS DELETED AND ALL REQUESTS BYPASS AUTHENTICATION. THIS METHOD IS FOR DEVELOPMENT USE ONLY. CHECK THE `NODE_ENV` VARIABLE BEFORE YOU CALL THIS METHOD.

### Edge cases for 7.1

**The word "warning" is also a code identifier.** Some languages use it as a
name (`warnings` in Python, `#[allow(warnings)]` in Rust, `console.warn()` in
JavaScript). Put the identifier in backticks. Use plain uppercase for the signal
word.

> **Non-STE:** Warning: the warnings module suppresses warnings by default.
>
> **STE:** CAUTION: THE `warnings` MODULE SUPPRESSES WARNINGS BY DEFAULT. THE OUTPUT FROM `warn()` CALLS IS NOT SHOWN. CALL `warnings.simplefilter('always')` TO SHOW ALL WARNINGS.

**A third-party library uses a different convention.** Translate `DANGER`,
`CRITICAL`, or `IMPORTANT` into the STE-Code signal words. Do not replicate the
third-party convention.

> **Third-party:** DANGER: This operation is irreversible.
>
> **STE-Code:** WARNING: THIS OPERATION IS IRREVERSIBLE. THE DATA CANNOT BE RECOVERED AFTER THE OPERATION COMPLETES. BACK UP THE DATA BEFORE YOU START.

**Generated code inserts its own warnings.** Do not modify generated comments;
the generator overwrites them. Add your own signal word in the documentation
that wraps the generated code. If the generated warning misclassifies the risk,
open an issue with the generator project.

> **Generated (leave as-is):** `// CAUTION: This method is deprecated.`
>
> **Your wrapper:** WARNING: THE `legacy/client.go` FILE CONTAINS DEPRECATED METHODS. DEPRECATED METHODS MAY BE REMOVED IN A FUTURE VERSION. THE REMOVAL OF THESE METHODS CAN BREAK YOUR APPLICATION. MIGRATE TO THE `v2/client.go` API.

**A BREAKING change overlaps with a WARNING.** Use one signal word. Mention the
breaking nature in the body.

> **Non-STE:** BREAKING: WARNING: The encrypt function now requires a key parameter.
>
> **STE:** WARNING: THE `encrypt` FUNCTION NOW REQUIRES A `key` PARAMETER. THIS IS A BREAKING CHANGE. UPDATE ALL CALLERS TO PASS A KEY ARGUMENT. IF YOU DO NOT PASS A KEY, THE FUNCTION THROWS AN ERROR AND THE DATA IS NOT ENCRYPTED.

**Translation.** Translate the signal words with the standard term for each
language. Do not invent new signal words. Keep the format identical: uppercase
word, colon, single space.

| Language | WARNING | CAUTION |
|----------|---------|---------|
| English | WARNING | CAUTION |
| Spanish | ADVERTENCIA | PRECAUCIÓN |
| French | AVERTISSEMENT | ATTENTION |
| German | WARNUNG | VORSICHT |
| Japanese | 警告 | 注意 |

### Grammar notes for 7.1

- **Placement.** The signal word is the first word of the instruction. Do not
  indent it. Do not put text before it (`Important: WARNING: ...` is wrong).
- **Punctuation.** The signal word is followed by a colon and one space.
- **Case.** Write the signal word in uppercase. Uppercase is part of the signal,
  not emphasis. `Warning:` and `warning:` are both wrong.
- **Structure.** Command or condition → consequence → risk escalation, in that
  order, in one sentence or several.
- **Verb form.** Imperative mood. Use "do not" for prohibitions. Do not use
  "should," "must," or "needs to."
- **Visual distinction.** In rendered output the signal word must stand out:
  bold, color, or a border in Markdown/HTML; an admonition directive
  (`.. WARNING::`) in reStructuredText. Do not rely on uppercase alone.

**Risk vocabulary.** Name the risk with a specific noun. Do not write
"problems," "issues," or "trouble."

| WARNING-level risk nouns | CAUTION-level risk nouns |
|--------------------------|--------------------------|
| Security breach | Unexpected behavior |
| Data loss | Performance degradation |
| System corruption | Incorrect results |
| Unauthorized access | Connection failure |
| Credential theft | Memory exhaustion |
| Data leak | Application crash |
| Privilege escalation | Configuration drift |

### Checklist for 7.1

- [ ] The signal word matches the real risk level, not the topic.
- [ ] Security, data loss, and system corruption use WARNING.
- [ ] Unexpected behavior, performance, and incorrect results use CAUTION.
- [ ] Mixed levels with one WARNING-level risk use WARNING.
- [ ] The signal word is first, uppercase, followed by a colon and a space.
- [ ] Only one signal word per instruction.
- [ ] The risk noun is specific, not vague.
- [ ] Technical code nouns are in backticks.
- [ ] Third-party conventions are translated, not copied.
- [ ] The signal word is visually distinct in the rendered output.

**See also:** Rule 5.3 (imperative form), Rule 7.2 (command or condition first),
Rule 7.3 (risk explanation), Rules 1.1/1.6/1.10/1.11 (approved words, one term
per concept).

---

---

<!-- rules-sec8.md -->

# Level 3 — Section 8: Punctuation Rules (Rules 8.1–8.7)

This slice covers STE-Code **Section 8 — Punctuation**. It adapts ASD-STE100 Issue 9, Section 8 for code documentation. Use it when you generate or review:

- README files, API reference docs, docstrings, inline comments
- commit messages, error messages, configuration comments, specification documents

**Scope boundary:** These rules govern documentation *prose*. They do **not** apply to source code or to any text inside code blocks / inline code spans (backticks). A JavaScript example that shows `const x = 5;` is correct and keeps its semicolon.

**Word-count limits referenced throughout:** procedural sentences ≤ 20 words; descriptive sentences ≤ 25 words. Sentence boundaries are the period (`.`), question mark (`?`), and exclamation mark (`!`).

---

## Rule 8.1 — Use All Standard English Punctuation Marks but Not the Semicolon (;)

**Rule:** You can use all standard English punctuation marks but not the semicolon (;).

**Why:** The semicolon (;) lets you pack two or more independent clauses into one sentence. In code documentation this makes sentences hard to parse — especially for non-native English readers. The semicolon also means different things in C, C++, Java, JavaScript, Rust, Go (statement terminator), which causes cognitive interference when the same symbol appears in prose.

**The fix is always the same:** split the semicolon-joined sentence into two or more independent sentences. Each stands alone with its own subject and verb.

### Examples

Non-STE: `Call the function to parse the response data; handle any errors that occur.`
STE:    `Call the function to parse the response data. Handle any errors that occur.`

Non-STE: `The cache is invalid after a write operation; you must flush it before the next read.`
STE:    `The cache is invalid after a write operation. You must flush it before the next read.`

Non-STE: `POST /sessions creates a new session and returns a token; the token must be included in the Authorization header of subsequent requests.`
STE:    `A POST request to /sessions makes a new session and returns a token. You must include the token in the Authorization header of all later requests.`

Non-STE: `Invalid port number; specify a value between 1024 and 65535.`
STE:    `The port number is not valid. Specify a value between 1024 and 65535.`

### Per-document-type guidance

- **README files:** Write a feature as one sentence, its rationale as a second. Use a connecting word (Rule 4.4) only if the relationship needs to be explicit.
- **API docs:** Write the primary effect as one sentence, the secondary effect as a second.
- **Docstrings / inline comments:** Use a bullet list for multiple return conditions. Use separate sentences for multiple side effects.
- **Commit messages:** Each body sentence states one fact. If you want a semicolon, you are combining two facts — split them.
- **Error messages:** Write the condition as one sentence, the recovery action as a second. Prefer the pattern `X is not valid. Do Y to fix this.`
- **Config comments / test docs:** Write purpose as one sentence, trade-off or assertion as a second.

### Edge cases

1. **Code blocks** — Semicolons inside fenced/indented code and inline backticks (`const x = 5;`) are code syntax, not prose. Keep them.
2. **Generated docs** — Semicolons spliced in by OpenAPI/JSDoc/protobuf generators are generator defects; you are exempt, but apply the rule to the source comments you write.
3. **Quoted strings** — Keep semicolons inside quoted error/log text. Surrounding prose must obey the rule.
4. **Super-comma lists** — Do not use semicolons to separate complex list items. Use a bullet list or table instead:
   - Non-STE: `The endpoint accepts three query parameters: sort, which sets the sort field; order, which must be "asc" or "desc"; and limit, which caps the result count.`
   - STE: bullet list with one line per parameter.
5. **Chat / informal** — Rule applies to formal docs (README, API docs, docstrings, commits, errors). It does **not** apply to chat or PR-thread discussion; commit messages are permanent and always apply.
6. **Regex / data strings** — Keep the semicolon inside the code span holding the data; prose uses periods only.

### Cross-references
Rule 1.1 (approved connecting words), Rule 3.1 (simple sentences), Rule 4.1 (short sentences), Rule 4.4 (connecting words), Rule 8.2 (hyphens).

---

## Rule 8.2 — Use Hyphens (-) to Connect Words That Are Directly Related

**Rule:** Use hyphens (-) to connect words that are directly related. A hyphen signals that two or more words function as a single concept.

**Five categories of hyphenation** (apply the same in code documentation):

1. **Compound adjectives before a noun:** `high-priority task`, `read-only file`, `thread-safe method`, `event-driven architecture`, `type-safe interface`, `run-time error`, `end-to-end test`, `point-to-point connection`, `server-side rendering`, `client-side validation`, `just-in-time compilation`, `fire-and-forget pattern`.
2. **Two-word fractions or numbers:** `seventy-two`, `one hundred and twenty-eight`, `three-fourths`, `forty-seven`.
3. **Uppercase-or-number + noun (shape/configuration):** `L-shaped bracket`, `T-shaped connector`, `64-bit register`, `8-byte alignment`, `128-bit value`, `3-prong connector`.
4. **Verb whose first part is a noun/other part of speech:** `dry-run`, `hot-reload`, `cold-start`, `hard-code`, `soft-delete`, `short-circuit`.
5. **Prefix ends in vowel, root starts with vowel:** `pre-initialized`, `re-entrant`, `de-allocated`, `anti-aliasing`, `re-indexed`.

**A hyphen is different from a dash.** The hyphen joins words into one concept; the dash (—) separates ideas, shows a range (`lines 12-48`), or signals a pause. Keep the two distinct.

### Examples

- Non-STE: `// The high priority task must acquire the write lock before it can modify the shared data structure.`
- STE:    `// The high-priority task must get the write lock before it can change the shared data structure.`

- Non-STE: `A read only file descriptor to open the configuration for parsing.`
- STE:    `A read-only file descriptor to open the configuration for parsing.`

- Non-STE: `git commit -m "Add end to end test for auth flow"`
- STE:    `git commit -m "Add end-to-end test for auth flow"`

### Per-document-type guidance

- **README:** `battle-tested`, `production-ready`, `cross-platform`, `well-documented`, `auto-generated`, `multi-threaded`.
- **API docs:** `non-negative integer`, `null-terminated string`, `zero-based index`, `read-only reference`, `thread-safe access`, `idempotent operation`, `fail-fast strategy`.
- **Docstrings:** `well-formed JSON string`, `null-terminated buffer`, `deep-copied instance`, `newline-delimited list`.
- **Commit/error:** `thread-safe cache`, `null-terminated input`, `non-negative integer`.

### Paradigm-specific key terms

- **OOP:** `read-only property`, `lazy-initialized singleton`, `thread-safe collection`, `reference-counted pointer`.
- **Functional:** `pure-function semantics`, `higher-order function`, `persistent-data structure`, `lazily-evaluated sequence`, `lock-free CAS loop`.
- **Procedural:** `null-terminated string`, `zero-initialized struct`, `statically-linked binary`, `newline-delimited output`.
- **Declarative:** `left-joined table`, `fully-qualified column name`, `user-provided input`, `well-formed document`, `base64-encoded value`.
- **Systems:** `move-semantics transfer`, `borrow-checked reference`, `memory-mapped I/O`, `copy-on-write page`, `lock-free stack`, `use-after-free bug`.

### Edge cases

1. **Hyphenated tool names** (`create-react-app`, `eslint-plugin-react`): keep the name as-is; do not add a second hyphen when used as a modifier.
2. **Code keywords** (`typeof`, `nonlocal`, `FULL OUTER JOIN`): hyphenate in prose when used as a compound adjective, but reproduce the keyword exactly in code spans.
3. **Generated output:** do not manually hyphenate generator output; configure the generator if you control it, else add a NOTE.
4. **Established unhyphenated compounds** (`filename`, `namespace`): keep the established form if it is unambiguous and consistent.
5. **URL path segments** (kebab-case, e.g. `/api/user-settings`): keep the exact path form; hyphenate prose compound adjectives normally.

### Grammar notes

- **Attributive (before noun) = hyphen; predicative (after verb) = no hyphen:** `The thread-safe collection` vs `The collection is thread safe`.
- **Adverb ending in -ly: no hyphen** — `a fully qualified name`, NOT `a fully-qualified name`.
- **"self-" prefix always takes a hyphen:** `self-contained`, `self-signed`, `self-healing`.
- **Temporary compounds:** `write lock` (separate) vs `write-lock` (compound noun before another noun); `run time` (noun phrase) vs `run-time` (compound adjective).

### Cross-references
Rule 1.1 (approved words), Rule 1.5 (technical nouns), Rule 1.9 (short technical nouns), Rule 1.11 (consistent terms), Rule 8.1 (punctuation), Rule 8.6 / 8.7 (hyphenated counts as one word).

---

## Rule 8.3 — Use of Parentheses

**Rule:** You can use parentheses for seven purposes:

1. References to code modules, diagrams, or text — `Call the request handler (Figure 3, Module A).`
2. Letters or numbers that identify items in a diagram or text — `Disconnect the endpoints (2) and (12) from the load balancer (8).`
3. Identifying work steps in a procedure — `(1) Install the dependency package (4) in the project directory (8).`
4. Including abbreviations — `A Command Line Interface (CLI) is a text-based interface...`
5. Giving singular and plural at once — `Before you run the test(s), set the environment variable(s).`
6. Explaining words or part of a sentence — `Increase the timeout slowly (not more than 1000 ms each step).`
7. Including an alternative — `Use the left (right) API key for the staging (production) environment.`

**Key patterns:**

- **Abbreviation placement:** always `Full Term (ABBR)` — never the reverse. After first definition, use only the abbreviation.
- **Never nest parentheses.** If you need a nested aside, split into sentences.
- **Parenthetical counts as a separate sentence** with its own word-count limit (Rule 8.5).
- **Period goes outside** the closing parenthesis for a sentence-ending parenthetical that is not a complete sentence (`Set the log level to debug (recommended for development).`). A complete-sentence parenthetical should instead be its own sentence.

### Examples

- Non-STE: `A Representational State Transfer Application Programming Interface, or REST API, is an architectural style...`
- STE:    `A Representational State Transfer Application Programming Interface (REST API) is an architectural style...`

- Non-STE: `Run the migration on all database shard servers, the primary and all replica instances, before you deploy.`
- STE:    `Run the migration on all database shard(s) before you deploy.`

- Non-STE: `Cannot find the config file you specified; looked in /etc/myapp/config.yaml, ~/.config/myapp/config.yaml, and ./config.yaml...`
- STE:    `Cannot find the configuration file (searched: /etc/myapp/config.yaml, ~/.config/myapp/config.yaml, ./config.yaml).`

### Per-document-type guidance

- **README:** define abbreviations on first use; reference related docs concisely `(refer to docs/getting-started.md)`.
- **API docs:** explain parameter constraints or units `(ms)`; wrap status codes `(404 Not Found)`.
- **Docstrings:** show types/ranges `(1 to 30000)`; only clarify what the type system cannot express.
- **Commit messages:** `(auth)`, `(issue #482)`, `(regression from v2.3)` — short scope/issue identifiers.
- **Error messages:** put diagnostic data (paths, line numbers, actual vs expected) at the end in parentheses.

### Edge cases

1. **Framework names that are common words** (`Flask`, `React`): add a brief parenthetical on first use — `React (a JavaScript UI library)`.
2. **Code keywords** (`()`, `<T>`): keep the code literal exact; explain in a separate sentence, not a nested parenthesis.
3. **Generated docs:** leave auto-inserted signatures/types untouched; apply the rule to human-written description fields.
4. **Nested parentheses:** split the sentence instead.
5. **CLI help text:** prefer alternative-use (`--verbose (--quiet)`) or explanation (`--timeout MS (default: 5000)`) patterns.

### Cross-references
Rule 1.1 (approved words), Rule 1.3 (approved meanings), Rule 1.9 (short technical nouns), Rule 5.1 / 6.3 (length, steps), Rule 8.2 (hyphens ≠ parentheses). Square brackets `[ ]` are reserved for optional parameters in code syntax — use parentheses, not brackets, for prose asides.

---

## Rule 8.4 — Colon in a Vertical List

**Rule:** In a vertical list, a colon (:) has the same effect on word count as a period and shows the end of a sentence.

- The introductory text before the colon obeys the length limits: ≤ 20 words (procedural), ≤ 25 words (descriptive).
- Each list item after the colon counts as a **new sentence** with its own limit (20 / 25 words).
- A colon before a vertical list is **always** a sentence boundary. Enumerated items are always vertical, never inline.

### Examples

Non-STE (31-word intro burying three cases):
`To handle all possible error conditions, the following exception types must be caught...: database connection timeouts..., authentication failures..., and validation errors...`

STE:
```
To handle possible error conditions, the error handler catches these exception types:
- Database connection timeout
- Authentication failure
- Validation error.
```

STE (config profiles):
```
The configuration file supports these environment profiles:
- Development
- Staging
- Production.
```

### Per-document-type guidance

- **README:** keep the introduction to the category; move version/compat notes into list items or a separate sentence.
- **API docs:** name the endpoint/resource and state what it enumerates; put type/default/optionality in each item.
- **Docstrings:** `Args:`, `Returns:`, `Raises:` introductions are usually trivially compliant; keep custom headers short.
- **Commit messages:** the subject line is NOT a list intro; keep any body intro short.
- **Error messages:** short intro (`The command failed for one of these reasons:`); each cause/recovery step is a separate sentence.

### Paradigm-specific guidance

- **OOP:** name the class/method in the intro; put type/default/constraint in each item.
- **Functional:** name the type/function; describe each variant/arm independently.
- **Procedural:** write a short goal before the colon, then imperative steps.
- **Declarative:** name the resource/option; one value/rule/setting per item.
- **Systems (safety-critical):** enumerate each precondition/safety condition as its own item; never bury it in the intro.

### Edge cases

1. **Inline code in intro:** each backtick token counts as one word (e.g. `docker-compose` = 1 word). Prefer intros with ≤ 15 words and few code tokens.
2. **Nested lists:** limit to one level; parent items are short category headings with their own colon.
3. **Code blocks inside list items:** the prose intro obeys the limit; the block itself is exempt.
4. **Long framework names:** move them into the list items; keep the intro generic.
5. **Generated docs:** obey the rule in the source comments you write; accept generator boilerplate (`Options:`, `Commands:`).

### Cross-references
Rule 1.1 (approved words in items), Rule 3.1 (one subject-verb-object per item), Rule 4.1 (length at two points: intro + each item), Rule 6.3 (procedural lists), Rule 8.1 (colon replaces semicolon-joined enumerations). Use a colon, **not** an em-dash (—), to introduce a vertical list.

---

## Rule 8.5 — Parentheses and Word Count

**Rule:** Text in parentheses counts as **one word** in the enclosing sentence. But the words inside the parentheses also form a **separate sentence** and must obey the length limit.

Identifiers in parentheses (a number, a letter, an alphanumeric identifier, or an abbreviation) count as one word.

Two categories of parentheticals:

- **Identifier parentheticals** — a number, letter, code, or abbreviation: `(10)`, `(EACCES)`, `(CI/CD)`, `(v2.1)`. Count as one word; no sentence-length limit (not prose).
- **Explanatory parentheticals** — prose that explains or qualifies: `(the DEBUG flag is off)`, `(the worker runs every 60 seconds)`. Count as one word in the main sentence but form a separate sentence subject to 20/25-word limits.

**Examples:**

- `Make sure that the DEBUG environment variable is set to false (the DEBUG flag is off).` — 12 words in the main sentence; the parenthetical is a 5-word separate sentence.
- `Remove the health check flag (10).` — 5 words; the identifier `(10)` is one word.
- `Configuration of a Continuous Integration/Continuous Deployment (CI/CD) Pipeline` — 7 words; `(CI/CD)` is one word.

**Key principle:** Use parentheses for clarifications, examples, and secondary qualifications. **Never** use parentheses for safety conditions, required steps, or warnings the reader must act on — those deserve their own sentence or a labeled block (`BREAKING`, `DEPRECATED`, `NOTE`).

### Examples

- Non-STE: `...production cluster (the DEBUG flag must be explicitly disabled for all production workloads to prevent accidental log leakage).`
- STE:    `Make sure that the DEBUG environment variable is set to false (the DEBUG flag is off).`

- Non-STE: `Cannot write to the configuration file (check that the file exists and is not read-only, that the parent directory is writable, and that your user account has the necessary file permissions...).`
- STE:
  ```
  Error: Cannot write to the configuration file.
  To fix this problem:
  - Make sure that the file exists.
  - Make sure that the file is not read-only.
  - Make sure that the parent directory is writable.
  - Make sure that your user account has the necessary permissions.
  ```

### Per-document-type guidance

- **README:** split long conditional asides into their own sentence before the instruction.
- **API docs:** keep parentheticals to identifiers/short qualifiers `(int, optional)`, `(default: 30)`; move conditional logic to a NOTE.
- **Docstrings:** keep parentheticals short; move algorithmic explanations out.
- **Commit messages:** issue refs `(#1234)` and scope `(auth)` are identifiers (one word each); put justification in the body, not parentheses.
- **Error messages:** each parenthetical `(Error code: EACCES)` is a separate sentence; recovery steps belong in separate sentences, not a parenthetical.

### Edge cases

1. **Function-call notation** (`authenticate()`, `parse(input)`): backtick-delimited code tokens are atomic — one word; the parens inside are not Rule 8.5 parentheticals.
2. **URLs in parentheses:** an identifier-like URL counts as one word; if the parenthetical also has explanatory text, that text forms a separate sentence.
3. **Nested parentheses:** do not use them; eliminate one level by making the outer aside its own sentence.
4. **Library names with parens** (`expect()`): keep in backticks (one word); parens are part of the identifier.
5. **Generated docs:** follow the rule for parentheticals you write; accept auto-inserted defaults.

### Cross-references
Rule 1.5 / 1.6 (technical nouns in parentheticals), Rule 3.1 (parenthetical is a simple sentence), Rule 3.3 (long parentheticals signal a paragraph restructure), Rule 4.1 (limit applies to the parenthetical too), Rule 8.1 (no semicolons inside parentheticals), Rule 8.4 (parenthetical inside a list item).

---

## Rule 8.6 — Elements That Count as One Word

**Rule:** When counting words for sentence length, count each of these as **one word**:

1. **Numbers** — `13`, `16`, `twenty-one`. (Do not count numbers that identify paragraphs or work steps — they are document numbering.)
2. **Numbers with units of measurement** — `10 ms`, `20 MB`, `10 μs`, `10 milliseconds`.
3. **Abbreviations** (acronyms/initialisms) — `VPN`, `OWASP`, `CI/CD`, `JWT`, `a.m.`.
4. **Alphanumeric identifiers** — `No. 1`, `E36L7`, `cache.miss.count`, `http.client.retry.max.attempts`.
5. **Quoted text** — `"Service Overview"`, backtick-quoted code (`C = (A - B) - 0.063 mm`), inline `<code>`, formulas. Each quoted span = one word.
6. **Titles, headings, and text on UI elements/labels** — `Operations Runbook`, `Error Handling and Recovery`, dialog/warning text you cannot change.
7. **Proper nouns** of individuals, groups, organizations, geopolitical entities — `Linus Torvalds`, `Apache Software Foundation`, `AWS Lambda`, `Azure AD B2C`.

**Why this matters:** applying Rule 8.6 collapses many multi-word elements into single-word counts, so sentences that look too long are often compliant. This is the largest reduction in API docs and README files (highest identifier/abbreviation density).

### Examples

- `The JWT authentication middleware must validate the signature of each incoming request. The token must have an expiry time of not more than 360 seconds to be valid for processing.` — `JWT` (1 word), `360 seconds` (1 word).
- `In application.properties, set http.client.retry.max.attempts to 5. Set http.client.retry.backoff.millis to 1000.` — each property name is an alphanumeric identifier (1 word); `5` and `1000` are numbers (1 word).
- `Call useUserProfile(userId) to get the current user profile.` — `useUserProfile(userId)` is quoted text (1 word).
- `In the Kubernetes manifest, set the checkout container to 250m CPU and 512Mi memory.` — `250m CPU`, `512Mi` are numbers with units (1 word each).

### Per-document-type guidance

- **README:** project names, badge URLs, version numbers, tool abbreviations each = 1 word.
- **API docs:** endpoint paths, HTTP status codes, parameter names each = 1 word.
- **Docstrings:** parameter/return/exception types each = 1 word.
- **Commit messages:** issue IDs, branch names, command names each = 1 word.
- **Error messages:** error codes, field names, type identifiers each = 1 word.

### Edge cases

1. **Framework names with "unapproved" words** (`Express`, `Swift`, `React`): proper nouns, 1 word; do not rewrite them.
2. **Code keywords** (`class`, `return`): quoted text, 1 word; keep them — do not replace with synonyms.
3. **Generated code/comments:** count as one word (category 6/7) when you cannot change them.
4. **Nested quoted text:** the outer backtick/`<code>` boundary defines the span; everything inside = 1 word.
5. **Semantic versions / hashes:** `1.2.3-alpha.1+build.456`, commit `a1b2c3d`, digest `sha256:abc...` = 1 word each. `Version 1.2.3` = 2 words.
6. **Document part numbers:** rule/section numbers (`Rule 8.7`), step numbers (`Step 3`), and ticket IDs (`PROJ-4821`, alphanumeric identifier) are not quantity counts.

### Cross-references
Rule 1.1 (proper nouns/identifiers exempt from approved-word check), Rule 1.5 / 1.6 (technical nouns), Rule 1.14 (American spelling of proper nouns), Rule 8.7 (hyphenated = one word), Rule 4.1/4.2 (sentence-length limits this rule feeds).

---

## Rule 8.7 — Hyphenated Words Count as One Word

**Rule:** Hyphenated words count as one word. A hyphenated group (compound adjective or long technical noun) is a single unit and counts as one word for sentence-length measurement.

### Case 1: Hyphenated compound adjectives (before a noun)

`read-only file descriptor`, `thread-safe singleton`, `event-driven architecture`, `low-latency cache`, `client-side rendering pipeline`, `end-to-end test suite`, `backward-compatible API`. The hyphen is a pre-noun signal only: after the noun or a linking verb, write the words separately and count each — `The singleton is thread safe` (5 words, not 4).

### Case 2: Long hyphenated technical nouns

The whole hyphenated group counts as one word; the following words are separate:
- `build-time environment variable` → `build-time` / `environment` / `variable`
- `client-side rendering pipeline` → `client-side` / `rendering` / `pipeline`
- `end-to-end test suite` → `end-to-end` / `test` / `suite`
- `check-out request handler` → `check-out` / `request` / `handler`

### Why it matters

STE-Code limits procedural sentences to 20 words and descriptive to 25 (Rules 4.1, 4.2). Counting each word inside a hyphenated term over-reports length and may break a limit the sentence actually meets.

- `The build-time environment variable must point to the staging cluster.` → 10 words (`build-time` is 1).
- `The thread-safe singleton must cache the read-only file descriptor.` → 9 words (`thread-safe` and `read-only` are 1 each).

### Interaction with other rules

- **Rule 8.2 (hyphens):** hyphenate per 8.2, then count the unit as one word per 8.7.
- **Rule 8.6:** a hyphenated word is a separate case — it is not also an abbreviation or identifier. Do not double-count.

### Common code-domain hyphenated terms (each = one word before a noun)

| Term | Type |
|------|------|
| read-only, write-only, thread-safe, event-driven | compound adjective |
| client-side, server-side, end-to-end, backward-compatible, low-latency | compound adjective |
| build-time, run-time, sign-in, check-out, request-response | technical noun |

When a term in this table follows the noun or a linking verb, write it as separate words and count each.

### Cross-references
Rule 8.2 (when to hyphenate), Rule 8.6 (other one-word elements), Rule 4.1 / 4.2 (sentence-length limits).

---

## Quick Reference — Section 8 at a Glance

| Rule | One-line summary |
|------|------------------|
| 8.1 | No semicolons in prose. Split into two or more sentences. |
| 8.2 | Hyphenate directly related words (compound adjectives, number+noun, prefix-vowel). |
| 8.3 | Use parentheses for refs, IDs, steps, abbreviations, `(s)`, explanations, alternatives. Never nest. |
| 8.4 | A colon before a vertical list is a sentence boundary; intro ≤ 20/25 words, each item is a new sentence. |
| 8.5 | Parenthetical text = 1 word in the main sentence but a separate sentence with its own limit. |
| 8.6 | Numbers, units, abbreviations, identifiers, quoted text, titles, proper nouns each count as 1 word. |
| 8.7 | Hyphenated words count as 1 word. |

**Remember:** these rules govern documentation *prose* only. Source code and text inside code blocks / backticks are exempt.

---

<!-- rules-sec9.md -->

# Level 3 — Section 9: Word & Sentence Rules (9.1–9.4)

STE-Code controlled-language rules for code documentation, distilled for LLM consumption.
Covers the four "word-level fallback and quality" rules: **9.1** (restructure when a
word-for-word replacement fails), **9.2** (use each approved word with its correct meaning
and part of speech), **9.3** (do not make phrasal verbs), and **9.4** (consistent style).

All examples are code-domain. No aerospace terms. Apply these rules whenever you generate
or rewrite code documentation (READMEs, API docs, docstrings, commit messages, error
messages, generated/AI output, infra-as-code, and systems docs).

## How to use this as an LLM reference

Apply the rules in this order for every sentence you write:

1. **Rule 1.1** — Use only approved words. Look up the word in the STE-Code dictionary
   (or the synonym preferences in Rule 9.4). Try a word-for-word replacement first.
2. **Rule 9.1** — If no approved word with the same part of speech exists, or a
   word-for-word replacement changes the meaning, restructure the sentence.
3. **Rule 9.2** — After you choose or restructure, check every approved word is used with
   its approved meaning and approved part of speech.
4. **Rule 9.3** — Replace any phrasal verb (verb + particle) with a single approved verb.
5. **Rule 9.4** — Use the same term, verb, and sentence structure for the same concept
   everywhere in the document and project.

Rule 9.1 is the escape hatch when the dictionary cannot supply a direct replacement.
Rules 9.2–9.4 are the quality gates that keep the result correct, unambiguous, and
consistent.

---

# Rule 9.1 — Use a Different Sentence Construction When a Word-for-Word Replacement Is Not Sufficient

**Core rule:** When a word is not approved, first try a word-for-word replacement with an
approved alternative of the same part of speech that keeps the meaning. If that is
impossible, rewrite the sentence with a different structure that uses only approved words
and keeps the same technical meaning.

**You must restructure when:**
1. The grammatical structure must change to fit the approved alternative.
2. A word-for-word replacement gives a meaningless or unclear result.
3. The approved alternative changes the meaning.
4. The word to replace is not in the controlled terminology at all.

When no replacement works, identify the purpose of the sentence and use different words,
verb forms, shorter sentences, or drop unnecessary information to get the same result.

## Quick check before restructuring
- Same part of speech? Approved alternative exists? Meaning unchanged? → **Replace** (no restructure).
- Otherwise → **Restructure** (Rule 9.1).

## Per-document-type guidance

**README files** — first doc a developer reads; keep clear and short.
- Passive descriptions → active instructions.
- Move complex explanations to a separate doc.
- Use bullet points, not long paragraphs.
- Remove marketing language ("leverages async I/O to facilitate…") → state the fact.

> Non-STE: This library leverages asynchronous I/O to facilitate high-throughput data processing.
> STE:     This library uses async I/O. It can process large quantities of data quickly.

**API documentation** — strict structure; keep parameter names unchanged (Rule 1.5).
- Restructure the description around the approved word.
- Use a different grammatical subject if the original subject depends on an unapproved word.
- Split compound descriptions into one sentence per parameter or behavior.

> Non-STE: This endpoint facilitates the retrieval of user profiles.
> STE:     This endpoint gets user profiles.

**Docstrings / inline comments** — most constrained; short, next to code.
- Keep code symbols unchanged. Never change a symbol to match an approved word.
- Use the approved verb form even if the sentence gets longer.
- If replacement is impossible in the space, drop the sentence and link to a longer doc.

> Non-STE: """Computes the aggregate of the supplied metrics and persists them."""
> STE:     """Gets the total of the metrics and saves them."""

**Commit messages** — short summary + blank line + body.
- Imperative summary ("Add feature", not "Added feature").
- Replace unapproved verbs with approved technical verbs.
- Complex change? Write a shorter message; put details in the PR.

> Non-STE: Implemented utilization of the cached connection pool to expedite request handling.
> STE:     Use the cached connection pool to make requests faster.

**Error messages** — short, clear, actionable; appear in logs/terminals.
- Tell the user what happened and what to do.
- Remove jargon the user cannot act on.
- Use "cannot" / "do not", keep code symbols and stack traces unchanged.

> Non-STE: The application encountered an unrecoverable exception while attempting to instantiate the connection pool.
> STE:     The application cannot start the connection pool. Look at the log for more data.

**Generated code / automated output** — the generated code itself is NOT subject to the
rules. Only your description of it must comply. Keep generated symbol names unchanged
(technical nouns, Rule 1.5); describe their function with approved words.

## Paradigm-specific guidance

**Object-oriented (Java, C++, C#, Python classes)** — class/interface/method names are
technical nouns.
- "provides an abstraction that facilitates" → "lets you use the same … methods".
- "contract" / "guarantee" / "enforce" (interfaces) → restructure ("All classes that use
  this interface must have a `save` method").
- Keywords "extend" / "override" / "specialize" are technical nouns when naming the
  keyword; unapproved verbs in prose → replace.

> Non-STE: The `BaseRepository` class provides an abstraction that facilitates data access operations across multiple database backends.
> STE:     The `BaseRepository` class lets you use the same data access methods with different databases.

**Functional (Haskell, Elixir, Clojure, Rust)** — type signatures are code (unchanged).
- "maps over" / "folds" / "lifts" are technical verbs when naming an operation; in general
  description, replace ("applies a function to each element").
- Monad/functor descriptions: state the practical effect, not abstract math.

> Non-STE: This function `fmap`s the provided transformation over the `Maybe` value, yielding a new `Maybe` that encapsulates the transformed result.
> STE:     This function applies the transformation to the `Maybe` value. If it is `Just x`, the result is `Just (f x)`. If it is `Nothing`, the result is `Nothing`.

**Procedural (C, Go, Bash)** — steps, memory, system calls.
- "allocate"/"free" are technical verbs; "deallocate" is not approved → "free"/"release".
- Shell "pipe"/"redirect"/"subshell" are technical nouns when naming features; unapproved
  as general verbs ("send the output of A to B").

> Non-STE: The program allocates a buffer on the heap, then deallocates it after processing to prevent memory leaks.
> STE:     The program gets a buffer from the heap. After it uses the buffer, it releases the memory to prevent memory leaks.

**Declarative (SQL, Terraform, Kubernetes YAML)** — desired state, not procedures.
- Keep field names as technical nouns; restructure the surrounding prose.
- "orchestrates the rollout of …" → "makes three copies of the Pod. If a Pod stops, the system starts a new Pod automatically."

**Systems (Rust ownership, C memory)** — keywords as code are unchanged; in prose check
the dictionary. "borrow"→"get a reference to"; "own"→"has"/"controls"; "move" is approved
but Rust-specific ("gives"/"moves").

## Edge cases
- **Framework names that are also unapproved words** (e.g. `Flask`, `Vite`, `Tailwind`):
  technical nouns, keep unchanged; never use as a verb ("Use Flask with the service", not
  "Flask the service").
- **Code keywords that conflict with approved words** (`use`, `move`, `return`, `break`):
  code-font keyword = technical noun; prose word follows the dictionary.
- **Quoted log/error output**: keep exact; your explanation follows the rules.
- **Restructuring loses precision** (e.g. security audit): split + add an approved-word
  clarifying note, or keep the term in code font with a glossary definition, or (internal
  expert audience) keep it as a technical noun with an approved-word definition on first use.

## Grammar patterns (reuse these)
- **Adjective → verb:** "X is visible" → "make sure that you can see X". ("is accessible" →
  "you can open"; "is extensible" → "you can add to".)
- **Noun → verb:** "perform the retrieval of X" → "get X". ("the service performs the
  validation of each request" → "the service checks each request".)
- **Split long sentences** before a conjunction/conditional, or between cause→effect,
  problem→solution. After splitting, each sentence must be self-contained.
- **Remove unnecessary info:** marketing adjectives, redundant modifiers, implementation
  detail that belongs in code, historical context that belongs in a changelog.

## Cross-references
Rule 1.1 (approved words — try first), Rule 1.4 (short sentences), Rule 1.5 (technical
nouns — do not replace), Rule 1.7 (don't verb technical nouns), Rule 1.12 (technical
verbs — do not replace), Rule 3.1 (simple tenses), Rule 5.1 (length limits), Rule 6.1
(active voice), Rule 9.2 / 9.3 / 9.4 (apply after restructuring).

---

# Rule 9.2 — Use Each Approved Word Correctly

**Core rule:** Every approved word in your documentation must be used with its **correct
meaning** and its **correct part of speech** (as listed in the STE-Code dictionary). Most
approved words have exactly one approved meaning; use only that meaning. Words approved as a
noun are not automatically approved as a verb, and vice versa.

**Decision rule:** Before using a word, read its dictionary entry. If the meaning or part of
speech you need is not the approved one, do a word-for-word replacement with a different
approved word, or restructure (Rule 9.1).

## Part-of-speech traps (most common violations)

- **"log"** — noun only (the record). Not a verb. "Log the error" → "Write the error to the log."
- **"help"** — verb only (to assist). Not a noun. "The config help" → "The configuration help text."
- **"damage"** — noun only. "The call damaged the stack" → "The call caused damage to the stack."
- **"execute"** — not approved. "Execute the script" → "Run the script."
- **"flush"** — approved as BOTH verb ("remove remaining data from a buffer") and adjective
  ("one surface fully touches a different surface"): "Flush the output buffer" vs "Make sure
  the connector is flush with the port."
- **"get"** (verb, obtain) vs **`GET`** (HTTP method, technical noun). "Send a GET request to get the data."
- **"set"** — verb ("put into a state") and noun ("a group of items"). "the set timeout" is
  ambiguous → "the timeout value that you set".
- **"run"** — verb only; noun only in "test run"/"dry run". "do a run" → "run the tests".
- **"build"** — verb and noun (the result/version). Prefer "build the project" / "the build
  output" over bare "the build".
- **"check"** — verb only; noun only in "health check"/"type check". "do a check" → "check".
- **"return"** — verb ("give back"); "the return value" OK (noun adjunct), but "the return of
  the function" is not. "The function returns a User object."
- **"fix"** — verb only. "a fix for the bug" → "correct the bug".
- **"update"** — verb only. "an update to the config" → "update the config".
- **"make"** — verb "to create". Avoid light-verb phrases: "make a call"→"call"; "make a
  request"→"send a request". "make a copy of the file" is OK (new thing created).
- **"use"** — verb; don't use "using" as a preposition ("Using this method, you can…" → "Use
  this method to…"). (`using` in C# is a keyword = technical noun.)

## Per-document-type guidance

**README** — every verb/noun must be approved and used in its approved sense. "leverage"→
"use"; "facilitate"→"help"/"let you"; "functionality"→"feature"; "capability"→"can".
"Run the tests after you build the project" (not "after the build").

**API docs** — precise. "GET" (method) vs "get" (verb); "set the timeout" vs "a set of
endpoints"; "the function returns a value" not "the return of the function".

**Docstrings** — "do" only as a general main verb ("Do the setup"); for specific actions use
the specific verb ("Run the migration"). "make a call"→"call"; "make a request"→"send a
request".

**Commit messages** — imperative summary with approved verb: "Add feature" not "Implement
feature"; "Add breaking change" not "Introduce breaking change". "fix" verb OK; "a fix" noun
not. "Update the config" not "Ship an update to the config".

**Error messages** — use "cannot" not "unable to"/"failed to": "Cannot open the config file".
Use "must" only when the user must act to continue. "If the problem continues, look at the
log for more data."

## Paradigm-specific guidance

**OO (Java/C++/C#/Python)** — keywords as code font are technical nouns; in prose they are
unapproved verbs: `extend`→"is a child of"/"inherits from"; `implements`→"uses the
interface"; `override`→"replaces the parent method"; `abstract`→"base class; you cannot make
an instance".

> Non-STE: The `PaymentProcessor` abstract class implements the `TransactionHandler` interface and provides a default implementation for the `validate` method, which subclasses can override.
> STE:     The `PaymentProcessor` base class uses the `TransactionHandler` interface. It gives a default `validate` method. Child classes can replace this method.

**Functional (Haskell/Elixir/Clojure/Rust)** — function names are technical nouns; in prose
use approved verbs: "maps over"→"applies … to each element"; "reduce"→"combine the elements
into a single value"; "filter"→"remove elements that do not match"; "apply"→"use".

**Procedural (C/Go/Bash)** — `free()` is a function name (technical noun); in prose "free the
memory" (verb) or "the memory is free" (adjective). "open" (verb) not adjective "available";
"close" (verb) not adjective "near". "read" verb, not noun ("read the data" not "do a read").

> Non-STE: After you allocate memory on the heap with `malloc`, you must deallocate it with `free` when the program no longer needs it. Failing to free allocated memory causes memory leaks.
> STE:     After you get memory from the heap with `malloc`, you must free the memory with `free` when the program does not need it. If you do not free the memory, the program uses more memory over time.

**Declarative (SQL/Terraform/K8s YAML)** — SQL keywords `CREATE`/`SELECT`/`DROP` are technical
nouns; in prose "make a table", "get rows", "remove the table". `terraform apply` is a
command; "use `terraform apply` to make the changes".

> Non-STE: The `Deployment` resource creates and manages a set of replicated Pods. It ensures that the specified number of Pods are running at all times.
> STE:     The `Deployment` resource makes and controls a set of Pod copies. It makes sure that the set number of Pods runs at all times.

**Systems (Rust/C)** — keyword meanings are technical: `move` (ownership) is an approved
technical verb; `borrow`→"get a reference to"; `drop` (Rust) is an approved technical verb;
"own"→"has". Keep `&`/`borrow checker`/`ownership` as technical nouns.

## Words approved as multiple parts of speech
- **build** — verb (construct) and noun (result/version). Be specific: "the build output", not bare "the build".
- **run** — verb; noun only in "test run"/"dry run".
- **set** — verb ("put into a state") and noun ("a group of items").
- **check** — verb; noun only in "health check"/"type check"/"lint check".
- **flush** — verb and adjective (see above).

## Edge cases
- **Framework/tool names that are also unapproved words** (`Express`, `Flask`, `Fresh`,
  `FastAPI`): technical nouns, keep in code font/capitalization; never verb them ("Use the
  `Express` framework to write your API routes" not "Express your API").
- **Keywords that are also approved words** (`use`, `move`, `return`, `break`): code-font
  keyword = technical noun; prose follows the dictionary. "Do not break the API contract" →
  "Do not change the API contract" (only physical separation uses "break").
- **Generated code symbols** — keep unchanged; describe their function with approved words.
  If public API, wrap with an approved name. If you author the generator, apply the rules to
  its templates.
- **Quoted errors/logs** — keep exact; explain with approved words.

## Grammar notes
- **One meaning per word:** each approved word has one approved meaning; express other
  meanings with a different word.
- **Noun-verb boundary:** approved-verb-only words must not be used as nouns ("run"→"run the
  program", not "do a run"); approved-noun-only words must not be used as verbs ("log"→"write
  to the log", not "log the error").
- **Dictionary is the source of truth:** when unsure, look it up. After restructuring
  (Rule 9.1), re-apply Rule 9.2 to the new sentence.

## Cross-references
Rule 1.1 (approved words), 1.2 (part of speech), 1.3 (approved meanings), 1.4 (approved
verb/adjective forms), 1.5 (technical nouns exempt), 1.7 (don't verb technical nouns), 1.12
(technical verbs — use their correct technical meaning), 9.1 (restructure when no replacement),
9.3 (no phrasal verbs), 9.4 (consistent style). The STE-Code Dictionary (A–Z) is the
authoritative reference.

---

# Rule 9.3 — When You Use Two Words Together, Do Not Make Phrasal Verbs

**Core rule:** Do not combine an approved verb with a preposition/particle to make a phrasal
verb (a phrase whose meaning differs from its parts). Replace a phrasal verb with a single
approved verb that has the same meaning. Only a few phrasal verbs are explicitly approved
(see list below), and they have a restricted meaning.

**Test:** If you can remove the preposition and the sentence keeps ~the same meaning, it is a
prepositional phrase (permitted, e.g. "write the config to the file"). If removing the
preposition changes the meaning completely, it is a phrasal verb (not approved, e.g. "write
up the report" = compose formally).

## Common phrasal-verb → approved-verb replacements
- put out → emit (compiler "puts out a warning" → "emits a warning")
- give off → return (function "gives off an error code" → "returns an error code")
- carry out → do (task "carries out the deallocation" → "does the deallocation")
- set up → configure / install / create (init with params = configure; place files = install; from nothing = create)
- run through → execute / complete
- look at → examine / inspect
- filter out → remove (note: "filter" alone is an approved technical verb)
- pick out → select
- kick off / kick in → start
- break down → divide / separate / analyze
- go on → continue
- hook into / tap into → connect to / subscribe to (also slang — doubly non-compliant)
- clean up → remove / delete / tidy
- fix up → correct / repair
- speed up → accelerate / make faster
- cut down → reduce / decrease
- wire up → connect
- strip out / rip out → remove
- flesh out → complete / expand
- hand off → send / transfer
- tear down → release
- spin up → start
- bring up → create
- hold onto → keep a reference to
- give up (lock) → release
- carve out → allocate
- reach out to → send a request to

## Per-document-type guidance
**README** — one approved verb per heading/paragraph: "Set up the project" → "Install the
project"; "Run through the quickstart" → "Complete the quickstart"; "Check out the examples" →
"Examine the examples".

**API docs** — verb must match the operation exactly: "Looks up a user" → "Finds a user"; GET
"gets" not "pulls down"; POST "creates"/"sends" not "puts in".

**Docstrings** — "Runs through and picks out" → "Examines and selects"; "Sets up and kicks off"
→ "Configures and starts".

**Commit messages** — one approved verb per change category (table above). "Clean up the
endpoints" → "Remove the endpoints".

**Error messages** — "Could not hook up to the database" → "Could not connect to the
database"; "blew up" → "failed"; "out of whack … sort it out" → "not consistent … correct it".

**Changelogs** — "did away with" → "removed"; "added back" → "restored"; "ironed out" →
"corrected"; "phased out" → "ended support for".

## Paradigm-specific guidance
**OO** — "sets up the object state" → "initializes"; "tears down resources" → "releases";
"hands off ownership" → "transfers ownership"; "looks up the dependency" → "finds"; "wraps up
the transaction" → "completes".

**Functional** — "maps over and filters out" → "applies a transformation to each element and
removes"; "pipes through" → "sends through"; "folds down" → "combines into"; "reaches out to"
→ "sends a request to".

**Procedural (C/Go/Bash)** — "free up" → "release"/"free"; "hands back" → "returns"; "reach
out and pull down" → "send a request and get"; "go through and pick out" → "examine and
select"; "put together and send off" → "make and send".

**Declarative** — "brings up EC2 instances" → "creates"; "spins up pods" → "starts"; "tears
down the index" → "removes"; "joins together" → "joins … with".

**Systems (Rust/C)** — "hands off ownership" → "transfers ownership"; "holds onto the
captured variable" → "keeps a reference to"; "gives up the lock" → "releases the lock";
"carves out a region" → "allocates".

## Approved phrasal verbs (restricted meaning — use as-is)
| Phrasal verb | Restricted meaning | Example |
|---|---|---|
| log in / log out | Start/end an authenticated session | "The user must log in before they can access the dashboard." |
| follow up | Take further action after an initial step | "Follow up the installation with the configuration step." |
| back up | Make a copy for safekeeping | "Back up the database before you apply the migration." |
| roll back | Return to a previous state | "Roll back the deployment if the health check fails." |

Do not use "sign in/out", "log on/off". "back up" is approved ONLY for copies, not movement
or support.

## Edge cases
- **Framework/tool names that are phrasal verbs** (`setuptools`, `cleanup`, `rollback`): the
  name is a technical noun (keep). Describe its behavior with an approved verb
  (`setuptools`.configures…, not `sets up`).
- **Keywords that are phrasal-verb components** (`break`, `continue`, `throw`, `catch`): as
  keywords/technical verbs they are approved ("the `break` statement exits the loop"; "the
  handler catches the error"). But "breaks out of the loop" / "catches up with the stream" are
  phrasal verbs → "exits the loop" / "synchronizes with the stream".
- **Not every verb+preposition is a phrasal verb** — prepositional phrases of location/direction/
  time are permitted ("runs on the server", "flows from A to B", "write the config to the file").
- **Generated docs** — apply the rule to the source docstrings; the generator output inherits
  compliance. Third-party generated docs you cannot edit need not be corrected.
- **No single approved verb exists** — apply Rule 9.1 (rewrite the sentence): "calls back the
  caller" → "sends the result to the caller through a callback"; "warms up" → "loads the data".

## Why this matters
Phrasal verbs cause **ambiguity** (multiple meanings), **non-native comprehension difficulty**,
and **poor searchability** (a search for "remove" misses "take off"/"strip out"). The
"one word where possible" principle: prefer a single approved verb over a 2–3 word phrase.

## Cross-references
Rule 1.1 (approved words), 1.2 (part of speech — the particle is not a direction preposition),
1.4 (approved verb forms), 1.11 (one term per concept — don't alternate "set up"/"configure"),
1.12 (technical verbs: don't replace "serialize" with "turn into a string"), 9.1 (rewrite when
no single verb fits), 9.2 (each word in a non-phrasal combo must carry its approved meaning).

---

# Rule 9.4 — When You Select Terminology or Wording, Always Use a Consistent Style

**Core rule:** Use the same term for the same thing, the same verb for the same action, and
the same sentence structure for the same type of instruction — everywhere in the document and
across the project. Different wording for the same concept forces the reader to ask "is this
the same thing?" and causes confusion and bugs.

**Three consistency domains (each maintained independently):**
1. **Lexical** — one term per concept (grep-auditable). Don't alternate "configuration file" /
   "settings file" / "config".
2. **Syntactic** — same structure for the same action. All setup steps start with an imperative
   verb + purpose clause; don't switch to passive/conditional for some.
3. **Semantic** — one meaning per term across files/modules/types. If "build" = "compile and
   link" in the README, it must not mean "compile, link, and package" in CI docs.

## Per-document-type guidance
- **README** — one term for the project artifact ("library" not "library"/"package").
- **API docs** — one name per endpoint/method/parameter; prose must match the schema field name
  (`createdAt` in schema → don't call it "creation date"/"timestamp"/"created time" in prose).
- **Docstrings** — use the same term as the function signature. Param `max_retries` → don't call
  it "maximum attempts"/"retry limit" in the body.
- **Commit messages** — one imperative verb per change category ("Add" for new features; don't
  mix "Introduce"/"Insert"/"Create").
- **Error messages** — same code → same text every time (`E_CONNECT_FAIL` must say the same
  string in every module so logs are searchable).
- **CLI help** — the `--output` description must match in `--help`, man pages, docs, and errors.

## Paradigm-specific guidance
**OO** — in a class hierarchy, reuse the base-class docstring template for overridden methods
(`connect()` everywhere says "Establishes a connection to the remote host, with …"). Don't
abbreviate class names inconsistently (`UserRepository` not `UserRepo`/`the user repo`).

**Functional** — one anchor phrase for pure functions ("returns a new list"); don't say
"produces a result"/"yields output". One metaphor for `IO` ("a description of an effect" not
"a computation"/"an action").

**Procedural (C/Go/Bash)** — predictable step structure on every I/O step ("Write the buffer to
the file descriptor" not "Output the data to the fd"). Same error-check pattern for every
`if err != nil`.

**Declarative** — same phrase per resource type ("a virtual machine in AWS EC2" not
"EC2 instance"/"AWS VM"/"cloud server"). Use `ConfigMap`/`Pod` consistently; never "config map"/
"configmap"/"configuration map".

**Systems (Rust/C)** — "ownership", "borrow", "lifetime", "move" are precise terms of art; never
substitute synonyms ("The function takes ownership of the buffer. The function moves the
buffer." not "takes possession"/"relinquishes control").

## Worked examples
- **Verb consistency:** "Install the dependencies. Then download the source. After that, set the
  environment variables. Finally, start the database." (not "fetch"/"set up"/"get … running")
- **Noun consistency across README/API/error:** "authentication library" is the only term (not
  "auth"/"module"/"package").
- **API reference structure:** every endpoint description starts with a third-person singular
  verb; "retrieves"/"gets" unified to "returns".
- **Commit convention:** all new features use "Add".
- **Error consistency:** one failure mode → one message "Cannot connect to the remote host" in
  every service (searchable across logs).
- **CLI flags:** each flag uses the same template "Enables/Disables [adjective] output".

## Edge cases
- **Framework-mandated terminology** — defer to the framework: use "props" (React) everywhere,
  never "properties"/"arguments". Consistency beats STE-Code synonym preference for proper names.
- **Generated docs** — fix the source docstrings, not the generated output. For conventional-
  commit changelogs, CI must reject non-standard verbs rather than emit inconsistent text.
- **Cross-project (monorepo)** — per-service docs follow the service glossary; system-level docs
  define a system-wide glossary that maps each system term to its service-level term.
- **Multiple valid industry names** — pick one ("GitHub Actions workflow" OR "pipeline"),
  document it in the glossary, never alternate.
- **Version rename** — each version's docs use that version's canonical name; migration guides
  must state the rename explicitly.

## Grammar notes
- **Cognitive load of synonymy** — every synonym forces a "is X the same as Y?" test that steals
  attention from content.
- **Structural parallelism** — a predictable template lets the reader scan for the action verb
  and skip scaffolding.
- **Term drift** — terminology drifts under multi-author maintenance. When you add content,
  search the existing doc for the terms you plan to use and match the convention.
- **Cross-language consistency** — Python `connect()` and TypeScript `connect()` must share the
  same description template.

## Preferred synonym table (pick one, use everywhere)
use (not utilize/leverage/employ) · start (not initiate/commence/bootstrap) · show (not
display/render/present) · make (not create/generate/produce) · get (not retrieve/fetch/obtain) ·
set (not configure/assign/establish) · check (not verify/validate/ensure) · remove (not
delete/eliminate/purge) · keep (not retain/preserve/maintain) · send (not transmit/dispatch/
forward). Variation in technical documentation is a defect, not a stylistic virtue.

## Cross-references
Rule 1.1 (approved words — cannot be consistent while alternating approved/unapproved),
Rule 1.3 (approved meanings — one meaning per word), Rule 1.5 (technical nouns exempt from the
dictionary but NOT from consistency), Rule 1.11 (one term per concept — lexical foundation of
9.4), Rule 9.1 (restructure rather than introduce a synonym), Rule 9.2 (a word used incorrectly
in one place breaks the consistency chain). The canonical synonym table (spec Section 1) is the
starting point; Rule 9.4 is the discipline that sustains it.
