payprobe-docs-and-writing
How to write and maintain PayProbe documentation. Load when: adding or updating any doc (guide, README, runbook), deciding WHERE a new document belongs (docs/ vs docs/history/ vs ADR vs PROGRESS vs RO
SKILL.md.claude/skills/payprobe-docs-and-writing/SKILL.md
GitHubPayProbe Docs and Writing
House manual for the documentation of record: what exists, what is trusted, where new writing goes, and the templates real artifacts follow. All paths are repo-root-relative. Facts date-stamped 2026-07-03 unless noted.
When NOT to use this skill:
- Outward-facing claims, licensing, positioning, "what may we say publicly" →
payprobe-external-positioning. - Whether a change needs an ADR/spec at all, gates and review discipline →
payprobe-change-control(it owns the ADR-vs-spec-vs-nothing decision; this skill owns the templates and the writing itself).
1. The docs map
Diátaxis structure (docs/README.md)
docs/ follows the Diátaxis framework — four modes organized by reader intent,
not by code structure. The folders are topic-named, not mode-named (there is
no docs/how-to/ directory); the mapping lives in the table in docs/README.md:
| Mode | Reader is… | Actual location |
|---|---|---|
| Tutorial | learning by doing, start to finish | docs/getting-started/quick-start.md, in-app Docs page |
| How-to guide | getting one job done | topic folders: docs/adapters/ (writing-an-adapter.md, grpc.md), docs/scenarios/ (code-step.md), docs/simulators/ (payshield-10k.md, visa-scheme.md, payshield-hsm-reference.md), docs/operations/load-test-runbook.md |
| Reference | looking a fact up | docs/operations/configuration.md (every env var + default), docs/operations/observability.md; live API reference is generated — Scalar at :8000/reference and :8100/reference, fed by each service's OpenAPI spec. Never hand-write API endpoint reference; it would drift |
| Explanation | understanding why | docs/architecture/ (overview.md, streaming.md) |
Historical working notes (project-review.md, standards-gap-analysis.md,
reports-renovation.md, the website-page prompts, and every finished build
spec) live in docs/history/ — moved there from the repo root and loose
docs/ on 2026-07-18 to keep the public landing view clean. Guides that
readers still need (e.g. participant-flow-end-to-end-guide.md) stay under
docs/. docs/adr/ holds numbered ADRs (0001–0007 as of 2026-07-18).
Note: docs/configuration/ and docs/deployment/ directories exist but are
empty (verified 2026-07-03) — do not put new docs there; operations content
goes in docs/operations/.
Build/migration specs (docs/history/) vs docs/
docs/history/ holds working documents for phased builds and migrations
(at the repo root until 2026-07-18):
*-SPEC.md, *-PLAN.md, *-SCOPE.md, docs/history/MIGRATION-DEPLOY-RUNBOOK.md,
docs/history/PLAN-end-to-end-mock.md. These are execution artifacts — status-stamped as
phases land (e.g. docs/history/DEFAULT-CONNECTION-MODEL-SPEC.md opens with
"Status: COMPLETE — Phases A–F all BUILT (2026-06-26/27)."). docs/ is for
readers; these specs are for the people/sessions executing a change. A spec
is done when its status line says so — it is then a historical record, not
deleted.
docs/history/PROGRESS.md and ROADMAP.md
docs/history/PROGRESS.md— the iteration log of the autonomous test-infra hardening campaign. Append-only iterations (newest first), each with measured before/after suite counts. It declares its own Definition of Done "MET (suite green, 195 passed / 0 failed)" and has not been extended since (last commit 2026-06-19). It is the canonical example of the measure, never assume style ("Root cause (measured, not assumed): …"). New hardening campaigns should reuse its entry format (template in §3).ROADMAP.md— versioned feature checklists (v0.1 Foundation … ). It is a planning artifact, not a status of record: last commit 2026-06-20, and checkboxes lag reality in both directions (v0.2 adapter items unchecked though several were since built; v0.3 still says "ngx-graph canvas integration" though ngx-graph was later replaced by a custom SVG canvas). Trust code, specs and the project review over ROADMAP checkboxes.
docs/history/project-review.md — the periodic honest assessment
A distinct genre: whole-codebase review "Generated 2026-06-20 against the
current tree", with dated Status update — review N sections appended as
follow-up passes land (reviews 3 and 4 are in the file). Structure: Snapshot
table (LoC + test posture per package) → What's strong → Weaknesses, ranked
(each with a severity tag, measured evidence — e.g. "77 except Exception and
~54 except …: pass" — and a concrete Fix:) → Quick wins with effort
estimates ("(hours)", "(minutes)") → New ideas / roadmap → Bottom line. It
criticizes the author's own code explicitly ("High — and it's my own code").
When you run a new review pass, append a ## Status update — review N (date)
section with a delivered-items table rather than rewriting history.
2. Docs of record vs known-stale
Docs of record (trust these): README.md (positioning, adapter table,
license/disclaimer), docs/operations/configuration.md, docs/adr/*
(status lines are honest), the docs/history specs' status stamps, docs/history/project-review.md,
the generated Scalar API references, and examples/ — examples are executable
documentation: every scenario in examples/scenarios/ runs in make test
(test_example_scenarios.py) and fails the build if it errors, so they cannot
silently drift.
Known-stale items (verified 2026-07-03) — fix these when touching nearby docs; do not propagate their claims:
| Item | What's wrong | Status |
|---|---|---|
docs/architecture/overview.md |
Last updated 2026-06-25. The project review's claim that it "predates the load-testing subsystem and gRPC" was addressed on that date (load fleet + gRPC are now in the diagram, verified by grep). But it is stale again: zero mentions of the chaos dial, resilience certification, Chronoscope replay, or stuck-run reconcile (all 2026-07 features). | Open task: refresh the overview after each major subsystem lands |
docs/history/project-review.md §9 |
Says report-service is a README stub with certification living in the orchestrator — written 2026-06-20; review 4 (2026-06-21) already records report_service as a real library with 15 tests. Re-verify before repeating either claim. |
Superseded within the same file; read newest status update first |
docs/README.md reference row |
Links scenarios/schema-reference.md, which does not exist (docs/scenarios/ contains only code-step.md). |
Broken link — fix or create the file |
CONTRIBUTING.md PR guidelines |
Requires "scripts/test-all.sh must exit 0" — that script does not exist (scripts/ holds only run_example_scenarios.py). The real gate is make test. |
Stale reference; use make test |
docs/history/PROGRESS.md counts |
"195 passed" was true at campaign close (2026-06-19); review 4 counts 366 backend tests (2026-06-21), more since. | Historical record, not current count |
ROADMAP.md checkboxes |
Lag reality both ways (see §1). | Planning artifact only |
3. Templates (extracted from the real artifacts)
ADR — from docs/adr/0001–0003
File: docs/adr/NNNN-short-slug.md (next free number). Sections marked
(0003) appear once a proposed ADR is implemented; (0001)/(0002/0003) show
which real ADR the section comes from — include what fits, keep the order.
# ADR-NNNN: <imperative, specific title>
**Status:** Proposed <!-- or: Accepted — implemented (see Implementation status) -->
**Date:** YYYY-MM-DD
**Deciders:** PayProbe maintainers (<names/roles>)
## Context
<What exists today, with file/symbol references. Why now.>
### What we can reuse <!-- 0002/0003: list existing seams before inventing -->
### Forces
<Constraints pulling in different directions.>
## Decision
<One paragraph, present tense: what we will do.>
## Options Considered
### Option A — <name> (chosen) <!-- mark the chosen one in its heading -->
**Pros:** …
**Cons:** …
### Option B — <name>
**Pros:** … **Cons:** …
### Option C — <name>
**Pros:** … **Cons:** …
## Trade-off Analysis <!-- 0001: prose comparing options; name the decisive factor -->
## Consequences
**Easier** / **Harder** / **Revisit** <!-- 0001 style -->
<!-- or -->
**Positive** / **Negative / risks** <!-- 0002/0003 style -->
## Rollout / sequencing <!-- 0002/0003: ordered, flag-gated steps -->
<!-- or -->
## Action Items <!-- 0001: numbered [ ] checklist naming concrete symbols -->
## Implementation status <!-- 0003 only, added when Status flips to Accepted:
what shipped, where, with test counts -->
## Open questions
## Notes <!-- out-of-scope + depends-on -->
House rules baked into the real ADRs: options name concrete existing machinery (LoadBus, worker_provisioner, run_control), not abstractions; consequences include a "Harder" / "risks" list — an ADR with no downsides is under-analyzed; status is never marked ahead of reality (0001 and 0002 are Proposed, not built as of 2026-07-03).
Build spec — from docs/history/DEFAULT-CONNECTION-MODEL-SPEC.md (and siblings)
File: <TOPIC>-SPEC.md (or -PLAN.md for pure migrations) under docs/history/ (new specs start there too).
# <Feature/model> — spec
**Status: <phase summary>.** <!-- lifecycle examples from real specs:
"Phase 1 in progress." (PARTICIPANT-FLOW-BUILD-SPEC)
"Phase X1 BUILT + Phase X2 BUILT (date, caveat)." (CONNECTION-ADAPTER-EXTENSION-SCOPE)
"COMPLETE — Phases A–F all BUILT (date)." (DEFAULT-CONNECTION-MODEL-SPEC)
Update this line as each phase lands; date every flip. -->
## Principle
<One-paragraph design rule the whole spec serves.>
## Current state (grounded in code)
<What exists NOW, with file paths. Key findings from reading the code —
this section is why the spec is trustworthy.>
## Target model
<The end state, concrete config/schema shapes.>
## Phases — each backward-compatible; the fallback is removed last
### Phase A — <name>
<Change, flag that gates it, tests that prove it, rollback step.>
### Phase B — …
## Backward compatibility
<What old data/config still works and how (guardrails).>
## Test matrix
<Table: case × expected behavior, old-model and new-model rows.>
## Risks / rollback
<Per-risk mitigation; the flag(s) that turn it all off.>
## Why this is worth it
The phase discipline is the reversibility non-negotiable in written form:
every phase flag-gated, rollback stated before defaulting ON. The companion
docs/history/MIGRATION-DEPLOY-RUNBOOK.md shows the operational half — see §4 dry-run rule.
PROGRESS iteration entry — from docs/history/PROGRESS.md
Append under ## Iterations (newest first):
### Iteration N — <one-line outcome> (category <a|b|c>)
- **Did:** <exact change: files, symbols, mechanism. Root cause stated as
measured, not assumed — quote the failing evidence.>
- **Added test:** `test_<name>` (<what it reproduces/proves>)
- **Result:** **<X> passed, <Y> failed** (was <X0>/<Y0>). No regressions.
- **Next:** <the measured gap you'll attack next, found while doing this one.>
Real entries never skip Result with suite numbers; "Added test" may become "Verified:" when the change is a dependency fix proven by the existing suite (Iteration 1 does this).
4. House style (inferred from the artifacts, verified)
- Honest status labels, everywhere. Every ADR/spec/proposal opens with a
status line:
Proposed,Accepted — implemented,Phase N in progress,BUILT (date),COMPLETE,proposal / brainstorm(docs/reports-renovation.md),🟡 partial(standards-gap-analysis.md). Unbuilt work is never described in the present tense as existing. If you flip a status, date it. - Evidence-linked claims: counts + dates. Numbers come from a command you
ran, stated with when: "180→183 passed", "366 backend tests (+29 since
review 3)", "77
except Exception". A claim without a count or a file/symbol reference reads as opinion in this codebase — anchor it. - Dry-run-first in runbooks.
docs/history/MIGRATION-DEPLOY-RUNBOOK.mdis the model: "the data steps are dry-run by default", and every mutating step is a pair — the plain command to review the plan, then the same command with?apply=true. New runbooks must follow this shape, plus a pre-flight section (make test-scenario,make portal-build, smoke-check curls) that even documents known pre-existing failures so the operator can tell signal from noise. - Docs change with the code — where that rule actually lives. It is NOT
in CONTRIBUTING.md. The verbatim rule is in
docs/README.md§"Contributing to the docs (docs-as-code)": "Docs live in this repo and ship with the code they describe — change them in the same pull request, reviewed together." What CONTRIBUTING.md itself requires for PRs: one PR per concern; all tests pass (it citesscripts/test-all.sh, which is stale — the real gate ismake test); a description (what/why/how to test); reference related issues; no credentials or real hostnames. Commit style is Conventional Commits — use thedocs(...)type for doc changes. - New adapter ⇒ README table row (CONTRIBUTING Step 8). Adding an adapter
is an 8-step checklist ending with: add a row to the README.md adapters
table (name, protocol, status
✅ Stableor🧪 Beta). Steps 2 and 7 also create docs: aREADME.mdinside the adapter package and at least one example scenario inexamples/scenarios/— whichmake testthen executes forever (executable documentation, §2). - Link new guides from the docs/README.md table and put them in the matching topic folder — a guide that isn't linked there doesn't exist for readers.
5. Where does a new doc go — decision table
| You are writing… | It goes… | Modeled on |
|---|---|---|
| First-run learning path | docs/getting-started/ |
quick-start.md |
| "How do I do X" task guide | topic folder: docs/adapters/, docs/scenarios/, docs/simulators/, docs/operations/ |
writing-an-adapter.md, load-test-runbook.md |
| Env var / config fact | extend docs/operations/configuration.md (don't fork a new file) |
— |
| API endpoint reference | don't write it — the Scalar /reference pages generate from OpenAPI |
docs/README.md §Interactive API reference |
| Why-it's-built-this-way | docs/architecture/ |
overview.md, streaming.md |
| A decision with rejected alternatives | docs/adr/NNNN-slug.md, template §3 |
ADR-0001..0003 |
| Phased build/migration with flags + rollback | docs/history/<TOPIC>-SPEC.md / -PLAN.md, template §3 |
docs/history/DEFAULT-CONNECTION-MODEL-SPEC.md |
| Operational steps to deploy/migrate | docs/history/ runbook, dry-run-first (§4.3) |
docs/history/MIGRATION-DEPLOY-RUNBOOK.md |
| Iteration log of a fix/hardening campaign | docs/history/PROGRESS.md entry, template §3 |
docs/history/PROGRESS.md |
| Feature planning / promises | ROADMAP.md checkbox (planning only, §1) |
ROADMAP.md |
| Periodic honest assessment | append ## Status update — review N (date) to docs/history/project-review.md |
reviews 3–4 |
| Standards/conformance posture | docs/standards-gap-analysis.md |
its 🟡/✅ per-standard format |
| Knowledge for future AI/junior sessions | .claude/skills/<name>/SKILL.md (§6) |
this library |
Unsure whether the thing needs an ADR vs a spec vs nothing at all → that
gating decision belongs to payprobe-change-control.
6. Maintaining the skill library itself (meta)
Skills live in .claude/skills/<name>/SKILL.md; the binding shared rules are
in .claude/skills/_AUTHORING-BRIEF.md — read it before writing or editing any
skill. Non-negotiable mechanics:
- YAML frontmatter with
name:and a trigger-richdescription:(symptoms, tasks, keywords that should make a session load it). Optionalscripts/dir for executable helpers. - Imperative runbook voice; copy-pasteable, repo-root-relative commands; never embed session-specific or user-home absolute paths; define jargon at first use; state when NOT to use the skill and which sibling covers it.
- Ground truth only: every path/flag/count verified against the repo, else
labeled
UNVERIFIED:or omitted. No oversell — statuses in skills obey the same honesty rule as §4.1. - Every skill ends with a "Provenance and maintenance" section: the verification date plus one-line read-only commands to re-check anything that can drift.
To re-verify / update a skill (do this when an ADR status flips, a spec phase lands, files move, or suite counts change):
- Run every command in its "Provenance and maintenance" section.
- Where output diverges from the skill body, fix the body — never the other way around; the repo is ground truth.
- Re-stamp the verification date; date any newly volatile fact.
- Claims you can no longer verify: mark
UNVERIFIED:or delete. Do not let a skill silently rot into fiction — a wrong runbook is worse than none. - Skills are repo files: they ship in the same PR as the change that invalidated them (same docs-as-code rule, §4.4).
Provenance and maintenance
All facts verified 2026-07-03 against the working tree. Re-verify with:
- Diátaxis map + docs-as-code rule verbatim:
sed -n '1,55p' docs/README.md - Actual docs folders (incl. empty configuration/ and deployment/):
ls docs/ docs/getting-started docs/adapters docs/scenarios docs/architecture docs/operations docs/simulators docs/configuration docs/deployment - Broken schema-reference link:
grep -n "schema-reference" docs/README.md && ls docs/scenarios/ - ADR statuses + section skeletons:
grep -n "^#\|^## \|^\*\*Status" docs/adr/000*.md - Root-spec status stamps:
grep -n "^\*\*Status\|^Status" *SPEC*.md *PLAN*.md docs/history/CONNECTION-ADAPTER-EXTENSION-SCOPE.md - PROGRESS entry shape + campaign close:
sed -n '1,70p' docs/history/PROGRESS.mdandgit log --date=short --format=%ad -1 -- docs/history/PROGRESS.md(expect 2026-06-19) - ROADMAP staleness:
git log --date=short --format=%ad -1 -- ROADMAP.md(expect 2026-06-20) andgrep -n "ngx-graph" ROADMAP.md - Review genre + §9 claim:
grep -n "^## \|^### " docs/history/project-review.mdandsed -n '112,118p' docs/history/project-review.md - Architecture overview freshness:
git log --date=short --format=%ad -1 -- docs/architecture/overview.md(2026-06-25 at authoring); staleness check:grep -ci "grpc" docs/architecture/overview.md(>0) vsgrep -ci "chaos\|resilience\|chronoscope" docs/architecture/overview.md(0 = still missing 2026-07 subsystems) - CONTRIBUTING PR rules + stale script:
grep -n "test-all\|same pull request\|Conventional" CONTRIBUTING.md; ls scripts/ - Adapter-table step:
sed -n '109,116p' CONTRIBUTING.mdandgrep -n "| Adapter | Protocol | Status |" README.md - Dry-run-first runbook:
grep -n "dry-run" docs/history/MIGRATION-DEPLOY-RUNBOOK.md - Skill-library rules:
sed -n '1,60p' .claude/skills/_AUTHORING-BRIEF.md