From 5f7cb66ee62493602fc72860197adfece62a92df Mon Sep 17 00:00:00 2001 From: Vijit Singh Date: Thu, 2 Jul 2026 15:06:20 -0500 Subject: [PATCH] chore: enforce docs voice + testing guidelines as guardrails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep the documentation and testing standards front of mind by making them discoverable and, where possible, CI-enforced instead of relying on reviewer memory. - docs/STYLE.md: the house documentation voice (opening line, imperative mood, NOTE warnings, concrete numbers, link-out) + the banned-word list + the code-is-source-of-truth accuracy rule. Points at testing-strategy.md. - scripts/lint-docs-voice.sh + make lint-docs-voice: fail CI if a banned marketing word appears in a prose doc (the one mechanizable slice of the voice guide). Wired into the per-surface lint job. Excludes STYLE.md itself, CHANGELOG, generated, and vendored markdown. Portable (no bash 4 mapfile). - .github/PULL_REQUEST_TEMPLATE.md: two checklist lines — docs in house voice, behaviour tested at the right tier with patch coverage clearing the gate. - CLAUDE.md: repo-root pointer so any Claude session loads CONTRIBUTING + docs/STYLE.md + docs/testing-strategy.md. Passes on develop (29 prose docs, no banned words); shellcheck + shfmt + yamllint + markdownlint clean. Co-Authored-By: Claude Opus 4.8 --- .github/PULL_REQUEST_TEMPLATE.md | 3 ++- .github/workflows/ci.yml | 4 ++-- CLAUDE.md | 13 +++++++++++++ Makefile | 5 ++++- docs/STYLE.md | 28 ++++++++++++++++++++++++++++ scripts/lint-docs-voice.sh | 27 +++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 CLAUDE.md create mode 100644 docs/STYLE.md create mode 100755 scripts/lint-docs-voice.sh diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7ece376d..34c1c5f1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,6 +16,7 @@ Closes # - [ ] `make test` passes locally (lint + dashboard pytest ≥ coverage gate + `pithead` shell suite + compose validation) - [ ] `pithead` and test scripts are shellcheck-clean (no new warnings) -- [ ] Docs in `docs/` (and the README, if relevant) are updated for any user-facing change +- [ ] Docs in `docs/` (and the README, if relevant) are updated for any user-facing change, in the house voice (`docs/STYLE.md`) +- [ ] New/changed behaviour is tested at the right tier (`docs/testing-strategy.md`); patch coverage clears the gate - [ ] This PR is focused on a single logical change - [ ] A linked issue exists for non-trivial changes diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e4e0023..f70ad8e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -241,6 +241,6 @@ jobs: export UV_INSTALL_DIR="$HOME/.local/bin" curl -LsSf https://astral.sh/uv/0.10.10/install.sh | sh echo "$UV_INSTALL_DIR" >> "$GITHUB_PATH" - - name: Lint JS/CSS (Biome), YAML, Markdown, proto (buf), TOML (taplo) + - name: Lint JS/CSS (Biome), YAML, Markdown, proto (buf), TOML (taplo), docs voice # Single source of truth: the Makefile targets. Tools run via npx/uvx/docker (preinstalled). - run: make lint-js lint-yaml lint-md lint-proto lint-toml + run: make lint-js lint-yaml lint-md lint-proto lint-toml lint-docs-voice diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..d86e481f --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,13 @@ +# Pithead — working notes for Claude + +Pithead is a Docker-Compose stack that runs a Monero + Tari merge-mining setup behind Tor. The `pithead` bash CLI renders `.env` and generated config from `config.json`, then drives docker-compose. + +Read these before making changes, and hold them for every change: + +- [`CONTRIBUTING.md`](CONTRIBUTING.md) — dev workflow, branch model (`develop` is the integration branch; `main` is released-only), how to run lint and tests. +- [`docs/STYLE.md`](docs/STYLE.md) — the house documentation voice. Every prose doc gets a voice + accuracy pass; the banned-word list is enforced by `make lint-docs-voice`. +- [`docs/testing-strategy.md`](docs/testing-strategy.md) — the fixed four-tier testing model. Test each behaviour once, at the lowest tier that proves it honestly. Do not invent a new model. + +Two standing bars for any change: it ships with the docs updated in the house voice, and with coverage at the right tier. Verify locally with `make lint` and `make test` (dashboard coverage ≥ 80%; patch coverage ≥ 90% via `make test-patch-coverage`; regenerate `docs/test-inventory.md` with `make test-inventory` if tests changed). + +Source of truth is the code: when a doc and the code disagree, fix the doc. Never invent a fact — mark `[TODO: verify upstream — ...]` instead. diff --git a/Makefile b/Makefile index 1259a7b2..96240f1e 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ test-inventory-check: ## Fail if docs/test-inventory.md is stale (CI drift guard test-integration: ## Run the live config-matrix integration suite (requires a test box; pass ARGS=...) bash tests/integration/run.sh $(ARGS) -lint: lint-sh lint-py lint-js lint-yaml lint-md lint-proto lint-toml ## Lint/format-check every surface +lint: lint-sh lint-py lint-js lint-yaml lint-md lint-docs-voice lint-proto lint-toml ## Lint/format-check every surface lint-sh: ## shellcheck + shfmt over the CLI, build/* container scripts, release + test scripts shellcheck --severity=warning pithead scripts/*.sh build/*/*.sh tests/stack/run.sh tests/stack/test_compose.sh \ @@ -61,6 +61,9 @@ lint-yaml: ## yamllint over all tracked YAML (config: .yamllint) lint-md: ## markdownlint over all Markdown (config: .markdownlint-cli2.jsonc) npx --yes markdownlint-cli2@0.18.1 +lint-docs-voice: ## Fail if banned marketing words appear in prose docs (house voice: docs/STYLE.md) + bash scripts/lint-docs-voice.sh + lint-proto: ## buf lint + build on the vendored Tari protos (config: .../tari/proto/buf.yaml) cd build/dashboard/mining_dashboard/client/tari/proto && \ docker run --rm -v "$$PWD":/workspace --workdir /workspace bufbuild/buf:1.71.0 lint && \ diff --git a/docs/STYLE.md b/docs/STYLE.md new file mode 100644 index 00000000..2474e0ee --- /dev/null +++ b/docs/STYLE.md @@ -0,0 +1,28 @@ +# Documentation style + +The house voice for every prose doc in this repo (`README.md`, `docs/**`, `CONTRIBUTING.md`, component READMEs). It matches the cadence of the p2pool, xmrig, and monero READMEs. + +Audience: competent, privacy-conscious Monero/Tari miners who run their own nodes and read marketing polish as a red flag. Assume they know mining, nodes, and wallets — don't define basics. + +## Voice + +- Open each doc with one factual line stating what it is. No pitch, no "whether you're X or Y", no benefits framing. +- Imperative mood for procedures: "Run", "Build", "Create a wallet" — not "You can run" or "Users should". +- Keep command blocks copy-paste ready, broken out per-OS or per-step, with one line of prose between them or none. +- State warnings flat. Use `NOTE:` for caveats. At most one `!` per doc, only where a mistake costs money, privacy, or data. +- Use concrete numbers, ports, and timings instead of vague qualifiers. +- Link out to deeper docs instead of inlining long explanations. Config keys live in [`configuration.md`](configuration.md) — link there, don't duplicate the table. + +## Banned words + +Do not use: leverage, robust, seamless, powerful, effortlessly, comprehensive, elevate, streamline, simply, unlock, empower, cutting-edge, blazing, lightning-fast. + +CI enforces this list (`make lint-docs-voice`, run by the per-surface lint job). The rest of the voice is reviewed by humans. + +## Accuracy + +The code is the source of truth. Verify every command, flag, default value, port, and path against the actual source — `pithead`, `docker-compose.yml`, `config.reference.json`, `config.py`, the Dockerfiles, the `Makefile`, and the test scripts. When the code and a doc disagree, correct the doc to match the code. + +For upstream claims (monerod/xmrig/Tari flags, version numbers, links to other projects), confirm against the upstream source before editing. Never invent a fact. If a claim can't be verified from the code or a fetchable source, leave a `[TODO: verify upstream — ...]` marker rather than guessing. + +Testing docs and coverage expectations live in [`testing-strategy.md`](testing-strategy.md). diff --git a/scripts/lint-docs-voice.sh b/scripts/lint-docs-voice.sh new file mode 100755 index 00000000..a7d351a0 --- /dev/null +++ b/scripts/lint-docs-voice.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Fail if a banned marketing word appears in a prose doc. The banned list is the one part of the +# house voice (docs/STYLE.md) that can be enforced mechanically; the rest is reviewed by humans. +set -euo pipefail + +BANNED='leverage|robust|seamless|powerful|effortlessly|comprehensive|elevate|streamline|simply|unlock|empower|cutting-edge|blazing|lightning-fast' + +# Prose docs only. Exclude the style guide itself (it lists the words), the changelog (a historical +# record), generated files, and vendored/third-party markdown. +files=$(git ls-files '*.md' | + grep -vxE 'docs/STYLE\.md|CHANGELOG\.md|docs/test-inventory\.md|THIRD_PARTY_LICENSES\.md' | + grep -vE '(^|/)(vendor|node_modules)/' || true) + +if [ -z "$files" ]; then + echo "docs voice: no prose docs to check" + exit 0 +fi + +# Filenames are space-free (git ls-files, this repo), so word-splitting into grep args is safe. +# shellcheck disable=SC2086 +if hits=$(grep -rniE "$BANNED" $files); then + echo "Banned marketing word(s) found — see docs/STYLE.md:" + echo "$hits" + exit 1 +fi + +echo "docs voice OK — no banned words in $(printf '%s\n' "$files" | wc -l | tr -d ' ') prose docs"