Keeping docs in sync
Pages under /business-logic/ describe the platform’s
rules and the lifecycle of the data they govern. They’re useful only as
long as they’re accurate. Three independent layers, ranked from automatic
to manual, keep them honest.
The convention they enforce
Every /business-logic/ page declares two frontmatter lists:
covers:
- api/src/features/account/logbook/**
- api/src/shared/middleware/logbook/**
owns:
- api/src/features/account/logbook/**covers:= “this page is partly about these code paths.”owns:= “this page is the primary documentation for these code paths — if these files change, this page is the first place that should be updated.”
See the covers/owns convention for the full data model. The three layers below all consume these declarations.
Layer 1 — Pre-push hook (automatic, local)
When you git push, a hook installed at .git/hooks/pre-push diffs your
branch against main and asks: “For each changed file, is it owned by
any doc page that you have not edited on this branch?”
If yes, the push is blocked with a message listing the offending files and the pages that own them. You then either:
- Open the named doc pages and update them, OR
- Add
docs-update: not-neededto a commit message on the branch (see the sentinel section below).
The hook is installed per-checkout, not committed. Run once after cloning:
cd docs
npm install
npm run docs:install-hooksThat copies the hook into your .git/hooks/ and symlinks the
docs-update skill into your Claude Code skill directory.
Layer 2 — CI check (automatic, on every PR)
.github/workflows/docs-checks.yml runs the same path-overlap check
on every PR. It’s the seatbelt for anyone who skipped step 1 or
bypassed the hook with --no-verify.
It posts the result as the docs-required status check on the PR.
A green check means either:
- No business-logic code changed, OR
- The corresponding
/business-logic/pages were updated too, OR - A
docs-update: not-neededsentinel was present in a commit message.
A red check means a business-logic change is undocumented. The PR can’t merge until the check is green.
Layer 3 — The /docs-update skill (manual, recommends actual edits)
The first two layers only flag — they tell you docs need updating, they don’t tell you what to write. The third layer is where the actual writing-assistance lives:
# Either via the Claude Code skill...
/docs-update
# ...or as a plain npm script:
npm run docs:updateWhat it does:
- Reads your branch diff against
main. - For each changed file, finds the doc page(s) that
owns:it. - Sends the diff and the affected pages to Claude with a prompt: “Given this code change, propose updates to these docs.”
- Writes proposed edits into your working tree — modifies the
.mdxfiles underdocs/directly. - Adds a per-branch changelog entry to
/changelog/, wrapped in a JSX-comment marker so re-runs update the entry in place rather than duplicating.
It never commits, never pushes, never writes outside docs/. You review
the proposed diff like any other change — accept, modify, or discard —
and commit the docs alongside your code change.
The docs-update: not-needed sentinel
Not every business-logic code change requires a doc update. Common genuine exceptions:
- A formatting / lint fix that changes no behaviour.
- A renamed internal helper with no API surface impact.
- A test-only change.
- A dependency bump.
For those cases, add docs-update: not-needed to any commit message on
the branch:
TUN-1234 Rename internal helper for clarity
Pure rename — no behaviour change. The covers/owns globs still match
because we renamed the file, not the directory it lives in.
docs-update: not-neededBoth the hook and the CI check honour the sentinel. They still log the files they would have flagged, so reviewers can sanity-check that you really meant it.
Quick reference
| You did this | What happens |
|---|---|
Changed api/src/features/logbook/lifecycle.js, no doc changes, no sentinel | Pre-push hook blocks; CI docs-required red |
Changed the same file, also updated docs/app/business-logic/logbook/page.mdx | Both green |
Changed only api/scripts/format-something.js (not in any covers: glob) | Both green — nothing flagged |
Pure dep bump in api/package.json, added docs-update: not-needed to the commit | Both green — sentinel respected |
Ran /docs-update, accepted its proposed edits, committed | Both green — your edits satisfy the check |
Where to look for more
- The covers/owns convention — the data model.
- Infra → GitHub → workflows — what
docs-checks.ymlactually does, line by line. docs/specs/003-docs-automation/in the repo — the spec that introduced all of this, with the rationale for each design decision.
You’re done with the getting-started zone. Make a tea, open a ticket, push a branch.