Skip to content

chore: gate the paths named in the docs (TRA-1219) - #166

Merged
mikestankavich merged 1 commit into
mainfrom
chore/tra-1219-contributing-md-is-rotten-in-all-three-p
Aug 31, 2026
Merged

mikestankavich merged 1 commit into
mainfrom
chore/tra-1219-contributing-md-is-rotten-in-all-three-p

Conversation

@mikestankavich

Copy link
Copy Markdown
Contributor

Refs TRA-1219 — item 3, the one the ticket calls the cause rather than a symptom. Scoped to trakrf/infra.

Items 1 and 2 are already done: infra's dead cp .env.local.example was fixed in #165, platform's quickstart in trakrf/platform#623, and item 2 is ble-mcp-test's. What was left is the reason all of it rotted.

The problem this fixes

Nothing reads CONTRIBUTING.md. No gate, no session, no CI, and no human between the day an env sample was renamed and the day someone tried to follow the quickstart. Infra's README.md stayed correct while CONTRIBUTING.md two directories away did not — same repo, same vintage, different consumers.

This gives those files a consumer. scripts/check-doc-paths.sh verifies that every repo-relative path named in the docs still exists. It makes no judgement about the prose; it catches the failure that actually strands a reader, which is being told to open a file that is not there.

Getting it quiet enough to be worth having

Deciding what counts as a path is the entire difficulty, and the obvious rule is useless. "Contains a slash" flags 86 tokens on this repo, almost all prose or Kubernetes shorthand:

N/A · preview/prod · web/API · deploy/trakrf-backend · cnpg.io/cluster
ghcr.io/clevyr/cloudnativepg-timescale · roles/storage.objectAdmin
fix/dns-record-drift · origin/main · docs/superpowers/  (an ignore pattern)

A gate that noisy gets ignored — which is exactly how the file it is checking rotted in the first place. So a token is checked only when both hold:

  1. its last segment carries a file extension, so docs/superpowers/ and deploy/trakrf-backend are out and helm/cnpg/README.md is in;
  2. its first segment is a real top-level entry of this repo, read from the tree at run time — so terraform/, helm/, docs/ are in while backend/… (a platform path quoted in a runbook), tmp/… and cnpg.io/… are out.

Plus one slash-free case: sample files (.env.local.sample). Narrow on purpose — in cp X.sample X the source must exist and the destination must not, so matching every .env* token would fail the very line it validates.

Globs, brace expansions and <placeholders> are rejected, not trimmed. Stripping argocd/root/templates/* down to its prefix and probing that would report a file nobody claimed existed.

86 false positives → 0 on this repo.

Verified against real history, not just fixtures

Replaying the pre-sweep docs from c83d9a4 against today's tree reports exactly the two genuine bugs and nothing else:

CONTRIBUTING.md: .env.local.example                    (renamed to .sample)
docs/prod-cutover.md: docs/superpowers/specs/…tra-850…md  (tree deleted in #165)

Both were found by hand during TRA-1128. Neither would have been caught by anything in CI.

Tests

21 cases, both directions, including a regression for each class of false positive the naive rule produced — k8s shorthand, image refs and IAM roles, prose with slashes, branch names, directory-shaped ignore patterns, another repo's paths, globs, brace expansion, placeholder arguments, and copy destinations that legitimately do not exist yet.

Two negative cases deliberately create the parent tree but not the file, since pre-creating the target would let a broken glob-rejection pass.

Wiring

  • .github/workflows/ci.yml — new doc-paths job running the tests then the checker
  • .claude/csw-validate.sh — same two lines, so it fires locally before a PR exists
  • CONTRIBUTING.md — one line telling a contributor the gate exists, so a CI failure is self-explanatory

Scope

Infra only. AGENTS.md is byte-identical across three repos and is deliberately untouched — editing it here would break TRA-1128's acceptance criterion 1.

This is offered as a candidate pattern for docs and platform, not a decision on their behalf. The ticket frames item 3 as a decision ("a CI job that runs the documented quickstart, or folding the parts that must stay true into a file something already reads"); this implements the first option for one repo so the others can judge it working rather than in the abstract.

What it does not do

It checks that referenced files exist. It does not check that documented commands still work — platform's go run cmd/migrate/main.go class of rot. That needs running the quickstart, which is a bigger and more fragile job, and is worth deciding separately.

Verification

.claude/csw-validate.sh green (ops-lib, doc-paths, tofu fmt, tofu validate across all roots, helm template). csw-gates --worktree main clean.

CONTRIBUTING.md rotted in every trakrf repo for one reason: nothing read
it. No gate, no session, no CI, and no human between the day an env
sample was renamed and the day someone tried to follow the quickstart.
This is item 3 of the ticket — the cause rather than the symptoms — for
infra only.

scripts/check-doc-paths.sh verifies that every repo-relative path named
in the docs still exists. It does not judge the prose; it catches the
failure that actually strands people, which is being told to open a file
that is not there.

Deciding what counts as a path is the whole difficulty, and the obvious
rule is useless. "Contains a slash" flags 86 tokens on this repo, nearly
all of them prose or Kubernetes shorthand — N/A, preview/prod,
deploy/trakrf-backend, ghcr.io/clevyr/..., roles/storage.objectAdmin. A
gate that noisy gets ignored, which is precisely how the file it checks
rotted. So a token is checked only when its last segment has a file
extension AND its first segment is a real top-level entry of this repo,
read from the tree at run time. Plus sample files (.env.local.sample),
narrowly: in `cp X.sample X` the source must exist and the destination
must not, so matching every .env* token would fail the line it validates.
Globs, brace expansions and <placeholders> are rejected rather than
trimmed into plausible-looking paths.

On this repo that is 86 false positives down to 0.

Verified against real history rather than only against fixtures. Replayed
the pre-sweep docs from c83d9a4 against today's tree, and it reports
exactly the two genuine bugs and nothing else:

    CONTRIBUTING.md: .env.local.example        (renamed to .sample)
    docs/prod-cutover.md: docs/superpowers/... (tree deleted in #165)

Both were found by hand during TRA-1128. Neither would have been found
by anything in CI.

21 unit tests cover both directions, including a regression case for
each class of false positive the naive rule produced. Wired into
.github/workflows/ci.yml as `doc-paths` and into .claude/csw-validate.sh
so it fires locally before a PR exists.

Scoped to infra deliberately. AGENTS.md is byte-identical across three
repos and is not touched here.

Refs: TRA-1219
@mikestankavich
mikestankavich merged commit a020723 into main Aug 31, 2026
21 checks passed
@mikestankavich
mikestankavich deleted the chore/tra-1219-contributing-md-is-rotten-in-all-three-p branch August 31, 2026 11:57
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