Skip to content

Write configs' docs, comments and names in one voice - #64

Merged
ahegyes merged 15 commits into
trunkfrom
fix/documentation
Nov 7, 2026
Merged

ahegyes merged 15 commits into
trunkfrom
fix/documentation

Conversation

@ahegyes

@ahegyes ahegyes commented Nov 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

The documentation, CI comments, input descriptions, step names and docblocks spoke in several voices and drifted from the files: the README carried the whole scoping contract inline, the scripts contract missed wp-env and lint:types, CONTRIBUTING gave the wrong timing for Node baseline changes, AGENTS.md broke its own shape, and no docblock named the \JsonException the scoping pipeline lets escape. This moves the scoping contract into docs/scoping.md, names every step and job as an imperative, writes each CI comment as one sentence, describes every input in one voice, indents the docs' JSON, XML and NEON examples with tabs, and gives the package a description that says why it exists.

Type of change

  • PHP source (Composer scripts, php-scoper config)
  • Reusable workflow (.github/workflows/reusable-*.yml)
  • PHPCS / PHPStan ruleset (php/quality-assurance/)
  • Node config (eslint, stylelint, playwright, tsconfig)
  • Documentation
  • Other

Checklist

  • Tests added or updated (PHPUnit suites under tests/Unit/)
  • The checks in CONTRIBUTING.md pass locally
  • If this changes a reusable workflow's inputs/outputs, docs/workflows.md is updated to reflect the new contract
  • If this changes a ruleset, downstream consumer behavior is considered (this repo ships to dev-trunk consumers immediately)

Breaking changes for downstream consumers

No input, output, script or file contract changes. Consumer-visible when the pin moves:

  • Check names: the reusable workflows' job names read as imperatives, so a caller's checks change name, such as composer validate → Validate composer.json, <script> → Run <script>, composer audit → Audit Composer dependencies, PHPUnit (…) → Run PHPUnit (…) and Build artifact → Build the artifact; a ruleset or branch protection that requires a check by name needs the new name.
  • Docs: the scoping contract lives in docs/scoping.md; the README's Dependency scoping section keeps the installation steps and links to it.

Composer moves roave/security-advisories to its latest advisory list,
and npm moves electron-to-chromium to 1.5.471, sass to 1.107.1 and
tslib to 2.9.1, with nothing moving down. The release-tools and
block.json locks need nothing. zizmor stays at 1.31.1, since 1.32.0
needs zizmor-action v0.8.1, which Dependabot's cooldown still holds.

Assisted-by: Claude Code:claude-opus-5-5
The README and the scripts contract showed JSON at two spaces and
the PHPCS ruleset and PHPStan examples at four, while the files they
stand for, the manifests, the shipped rulesets and the NEON profiles,
indent with tabs under the repository's .editorconfig, so a copied
example arrived indented against the consumer's own editor config.

The 16 blocks now indent with tabs, as the files they show do; the
YAML examples keep two spaces. The change is whitespace only.

Assisted-by: Claude Code:claude-opus-5-5
The workflows name their steps in two voices: telegraphic forms such
as "Assert required files present" and "Redirect wp-env at built
artifact" beside sentences such as "Find the main plugin file", and
the audit steps by their bare commands. The tests that run those
steps by name now look for the imperative names, so they fail until
the workflows take them.

Assisted-by: Claude Code:claude-opus-5-5
Step names mixed telegraphic forms ("Assert required files present",
"Record archive digest") with sentences ("Find the main plugin file"),
carried parenthetical narration ("dev — runs the scoping pipeline",
"for wp-env"), spelled the verb "Setup", and were left off some setup
steps while the same setups elsewhere had them. Job names mixed cases
and forms, such as "PHP Lint", "PHP 7.4 syntax" and "Plugin Check
fixture build".

Every step and job now reads as an imperative in sentence case, with
an article where English takes one, so Quality's lint job reads
"Lint PHP" as in the other repositories. Every step but the
repository checkout is named, a matrix value stays in its
parentheses, and the release's development-install note moves into
the comment above it. No ruleset requires a check by name.

Assisted-by: Claude Code:claude-opus-5-5
The input descriptions, which docs/workflows.md calls the
authoritative wording, used two voices: "e.g." and "Leave empty to"
in the PHPUnit and Playwright workflows beside "such as" and
"Empty uses" elsewhere. Seven had no final period, the syntax
check's example showed literal backslashes because a single-quoted
YAML string keeps them, the wp-env config input narrated a migration
off the implicit dev and tests split, the WordPress version inputs
named a consumer plugin's .wp-env.json although the config file is
an input, and the Playwright script's description told callers to
override the default with the default.

Each description now takes the docs tables' voice, ends with a
period and carries no backticks, dashes or abbreviations, and the
Playwright table's wp-env-core row matches the PHPUnit one.

Assisted-by: Claude Code:claude-opus-5-5
Several workflow comments broke the repository's one-sentence rule:
two sentences or two clauses joined by a semicolon or a dash, a
sentence wrapped over two lines, a lowercase tool name opening the
line, and abbreviations such as "repo". The workflow checks restated
the integer check's reason in a second comment, the block.json check
described the joined string it avoids, and the CodeQL input named a
caller's Quality workflow. The wp.org assets placeholder carried no
reason, though the deploy job's download depends on it.

Each comment now reads as one capitalized sentence on one line, the
duplicate goes, and the placeholder says why it exists.

Assisted-by: Claude Code:claude-opus-5-5
The ESLint and Stylelint baselines each carried a second header line
that restated the ignore list beneath it. The .distignore baseline's
second line told the reader to copy the file, an instruction that
stays behind as a wrong one in every copy, and its secret-material
note ran over two lines with an aside that means nothing inside a
copied file. The PHPCS smoke's plugin stub declared WordPress 7.0
under the profile's 7.1 floor, and its descriptions ran to a
paragraph.

The restating lines and the copy instruction go, the secret note is
one sentence, and the stub declares 7.1 with one-line descriptions.

Assisted-by: Claude Code:claude-opus-5-5
The scoping pipeline decodes manifests and symbol lists with
JSON_THROW_ON_ERROR, but no docblock named the \JsonException that
escapes, which does not extend RuntimeException. The collector matches
function_exists() case-sensitively beside the lowercased define() and
class_alias() matches without saying why. GlobalTagVisitor's docblock
narrated the code below its reason, its @var template braced a simple
property, and the php-font-lib recipe comment joined two sentences
with a semicolon.

Each function a \JsonException leaves names it in @throws, the
case-sensitive match states its reason, and the docblock and the
comments are one sentence of why.

Assisted-by: Claude Code:claude-opus-5-5
The README is meant to be an index, but its Dependency scoping
section carried the whole scoping contract inline: how names select
packages, every step and failure of a run, the stubs and text-domain
declarations, and the recipe format. Its Playwright paragraph ran to
120 words of factory internals, and its Development section repeated
commands that CONTRIBUTING.md lists in full.

docs/scoping.md now holds the contract, moved unchanged under a scope
sentence and section headings, and the README keeps the installation
steps and a link. The Playwright paragraph states where specs and
artifacts live and how to replace the web server's command, the
Development section links to CONTRIBUTING.md and the tests guide, and
AGENTS.md names the new document.

Assisted-by: Claude Code:claude-opus-5-5
The scripts contract says it names the scripts the workflows and
shared configs read, but it left out wp-env, which the Playwright
base's web server runs, so a project without it fails only a local
npm run test:e2e. Its conventional lint list left out lint:types,
the lane the tsconfig baseline exists for, and the README never said
that the tsconfig takes effect only through a project's tsc script.
The names the repositories share for recurring jobs, such as setup,
packages-install, audit and quality-check, were written down nowhere.

The Fixed names table lists wp-env, the conventional lint list adds
lint:types, a Conventional names table gives each shared script's
job, and the README says why the tsconfig needs a tsc script.

Assisted-by: Claude Code:claude-opus-5-5
The README's tsconfig row copied every option of the file in another
order, so it went stale with each option change, the ESLint row left
out the console allowance the base adds, and the Stylelint example
copied the base's rules into a new object for a reason that only
explains the spread. Nothing said that the package aliases prettier
to wp-prettier, its one runtime dependency, which decides what a
consumer's wp-scripts format runs. The PHPStan floor key lacked its
WPCompat parent, and the Plugin Check note said a parser "stops at"
PHP 8.4 syntax, which reads as support up to it.

The rows describe each baseline's intent, the Stylelint example
spreads the base alone, one sentence names the alias, the floor
reads WPCompat.requiresAtLeast, and the parser "fails on" the syntax.

Assisted-by: Claude Code:claude-opus-5-5
CONTRIBUTING.md said a Node baseline change reaches consumers at
their next Composer update, while npm consumers get it only when
they move their pin, so contributors judged its impact by the wrong
timing; the prettier alias, which changes what every consumer's
formatter runs, was missing from that paragraph. The
never-automerge rule for release pin bumps lived in CONTRIBUTING.md
and SECURITY.md alike, the setup step used a plain composer install
beside the repository's packages-install script, and SECURITY.md's
scope gave vulnerability classes as examples of a component and
addressed the reporter in a second voice.

CONTRIBUTING.md states both timings and the alias, uses
packages-install, and links to SECURITY.md for the pin-bump rule,
whose scope sentence now reads as a list of components.

Assisted-by: Claude Code:claude-opus-5-5
AGENTS.md held thirteen unnumbered conventions without bold leads,
against the shape the other repositories' agent files follow, with
the docblock, comment, Markdown and commit rules mixed in among the
repository's own. Its naming rule claimed every shared config is
named <tool>.dist.<ext>, which only the PHPCS and PHPStan profiles
are, its floor rule named the PHPStan key without its file and
WPCompat parent, and its first command was a plain composer install
beside the repository's packages-install script.

The nine repository conventions are numbered with bold leads, the
four style rules sit in a Style section before Limitations, the
naming rule covers both kinds of shared file, the floor names its
file and full key, and the commands start with packages-install.

Assisted-by: Claude Code:claude-opus-5-5
The template asked only that composer test pass locally, while
CONTRIBUTING.md lists the full set of local checks CI mirrors: the
quality check, the Node lints and smoke, both audits, actionlint and
zizmor. A contributor who ticked the box could still fail CI on
everything the unit suite leaves out.

Assisted-by: Claude Code:claude-opus-5-5
composer.json and the README opened with two different lists of what
the package holds, PHPCS, PHPStan and php-scoper configurations,
Node baselines and workflows, which grow with every feature and
differed from each other and from GitHub's description.

Both now carry the sentence GitHub already shows: shared tooling
that lets WordPress projects be checked, scoped and released the
same way.

Assisted-by: Claude Code:claude-opus-5-5
@ahegyes ahegyes changed the title Fix/documentation Write configs' docs, comments and names in one voice Nov 7, 2026
@ahegyes
ahegyes merged commit 4626fad into trunk Nov 7, 2026
37 checks passed
@ahegyes
ahegyes deleted the fix/documentation branch November 7, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant