Code Standards¶
This page covers three application repositories — CPSV Editor (ttl-editor), Linked
Data Explorer, and RONL Business API — that share a common tooling convention:
Husky-managed git hooks, npm workspaces, and four identically named root scripts. It
documents what their tooling actually enforces, measured from each repository's own
configuration rather than assumed to be uniform.
Linting and formatting¶
Every repository exposes the same four commands at its root, but the shape behind them differs — RONL Business API and Linked Data Explorer are npm workspaces fanning out across multiple packages; CPSV Editor is a single package.
| Command | RONL Business API | Linked Data Explorer | CPSV Editor |
|---|---|---|---|
| Lint | npm run lint |
npm run lint |
npm run lint |
| Lint, fixing what it can | npm run lint:fix |
npm run lint:fix |
npm run lint:fix |
| Format | npm run format |
npm run format |
npm run format |
| Format, check only | npm run check-format |
npm run check-format |
npm run check-format |
At the root, the four names line up. Underneath, they don't. RONL Business API's root
check-format isn't a workspace fan-out at all — it runs prettier --check directly
against the whole tree (**/*.{ts,tsx,json,md}), so it reaches every package in one
pass regardless of what each package calls its own script. Linked Data Explorer's root
check-format instead runs npm run check-format --workspaces --if-present, which
invokes whichever workspace defines a script of that exact name and silently omits
any that don't, because --if-present treats a missing script as nothing to do rather
than an error.
That distinction was not academic. Linked Data Explorer's backend package used to name
its script format:check, not check-format — a one-character difference from what the
root fan-out was looking for. The root command exited 0 on every run, having quietly
checked only the frontend the whole time. The fix keeps check-format as the backend's
canonical name and format:check as an alias that delegates to it, so the workspace is
picked up under either name. The practical rule this leaves behind: if you're running a
formatter or linter by drilling into a single workspace (npm run check-format
--workspace=@ronl/backend, for example) rather than from the repository root, check
that package's own package.json for the script's actual name — don't assume it matches
the root's.
Git hooks¶
All three repositories wire the same two hooks through Husky, and they gate the same two things everywhere: staged-file linting and formatting on commit, full linting and formatting on push.
pre-commitrunslint-staged, formatting and linting only the files staged for that commit (viaprettier --writeand each affected workspace'slint:fix).pre-pushruns the full lint and format-check across the repository (RONL Business API'spre-pushalso rebuilds the shared package and runs a type check first, since its packages depend on it).
None of the three repositories' git hooks run the test suite. Neither pre-commit
nor pre-push invokes npm test anywhere. A passing hook is not evidence your change
didn't break a test — only CI, or running the suite yourself, tells you that. Since
August 2026 CI closes that gap on the way in as well as on the way out: in CPSV Editor
and RONL Business API a failing check now blocks the merge, not just the deploy — see
Enforcement below.
CI¶
Every deploy pipeline that has something to test now runs the suite before it builds, and a failing test blocks the deploy. That has only been true since 20 August 2026 — before then CI and the hooks left the same gap, and RONL Business API's public-site package had the only real test gate anywhere.
RONL Business API — nine workflows: an acc/prod pair for each of four
packages, plus the supply-chain audit:
| Workflow pair | Lint | Type-check | Tests | Notes |
|---|---|---|---|---|
azure-backend-* |
✅ | – | ✅ | Builds and uploads a deployment artifact; it does not deploy |
azure-frontend-* |
✅ | – | ✅ | Also runs npm run test:perf, the wall-clock budget, as a step of its own |
azure-publicsite-* |
✅ | ✅ | ✅ | Its build additionally gates on a prerender and a bundle-cleanliness check |
azure-pa-demo-* |
✅ | ✅ | ✅ | Also installs Chromium and runs the Playwright E2E suite before the bundle gate |
The frontend's performance budget runs separately because it asserts wall-clock time, which means nothing while 133 test files compete for cores — see The performance budget.
Linked Data Explorer — seven workflows on acc: six deployment workflows plus
the supply-chain audit gate added in v2026.08.7. Both backend and both frontend
workflows run lint and then the suite before building. The two ropa-site workflows run
neither, and correctly so: that package is a static index.html plus a
staticwebapp.config.json, with no build and no test script to run.
Unlike the other two, the Linked Data Explorer's CI does deploy its backend — the
backend workflows end in azure/webapps-deploy, where RONL Business API's end in an
uploaded artifact that a developer deploys by hand. Its backend workflows trigger on
push only, though, so no pull request runs the backend suite; a break surfaces on acc
after merge, where npm test gates the deploy step.
CPSV Editor — three workflows: both Azure Static Web Apps workflows, acc and
main alike, run npm ci, npm run lint and npm run test:ci ahead of the deploy
action, and a third runs the supply-chain audit.
None of this replaces running the suite yourself before opening a merge request — and a green local run is weaker evidence than it looks. RONL Business API's first gated run failed on test files that had been latently broken for weeks: ts-jest caches type diagnostics per file, so a warm local cache kept skipping the check that CI, starting cold, performed immediately. Clearing the cache reproduced it at once.
Enforcement: what blocks a merge¶
Running a check and being able to block on it are different things, and until August
2026 these repositories only did the first. CPSV Editor and RONL Business API
now each carry a branch ruleset named acc supply-chain gate, active on
refs/heads/acc with no bypass actors, combining two rules:
required_status_checks→ theauditcontext must passpull_request→ a pull request is required (0 approvals; these repositories have a single maintainer, and GitHub does not permit self-approval)
Both rules are needed together — requiring the status check alone would still let a
direct push to acc sail past it. The practical effect is that git push origin acc
is rejected outright in all three repositories, including for releases and including
for the repository owner. Linked Data Explorer adopted the same ruleset in v2026.08.7;
all three are named acc supply-chain gate and carry zero bypass actors.
Supply-chain hardening¶
Alongside the test gate, all three application repositories — CPSV Editor (the pilot,
v2026.08.2), RONL Business API, and Linked Data Explorer (v2026.08.7) — have
adopted a common set of pipeline controls: every uses: reference pinned to a commit
digest rather than a tag, permissions: contents: read as the workflow default,
persist-credentials: false on checkout, a blocking zizmor audit job, and Renovate
maintaining the digests under a 14-day cooldown with a no-cooldown lane for security
advisories. What cannot be pinned is written down in each repository's
SECURITY-PIPELINE.md rather than glossed over.
The rollout is not identical across the three. RONL Business API has taken the v7
action majors; the CPSV Editor and the Linked Data Explorer remain on v4, and the
Linked Data Explorer carries one actions/checkout at v3.7.0 — all pinned by digest,
but pinned to older majors. No main branch carries any of this, so the gate
protects the acceptance path only.
Supply-Chain Pinning covers the mechanism, the measured results (16 findings to zero in the CPSV Editor, 49 in RONL Business API, 40 in the Linked Data Explorer), what the gate deliberately does not protect, and the order to copy the four artifacts into the next repository.
Commit messages¶
Follow Conventional Commits, as
described in Contributing → Commit your changes. None
of the three repositories above enforce this mechanically — Norm Editor does: its
commit-msg and pre-push git hooks reject any commit whose subject line does not
match the Conventional Commits pattern, so a non-conforming message there hard-fails
rather than merely failing review.
No Claude attribution trailers. If you're using an AI assistant to help prepare a
commit, the commit message ends with its substantive body and nothing else —
Co-Authored-By and similar trailers are not added, regardless of what a tool's default
template suggests appending. This applies whether the change came from Claude Code, the
superpowers plugin, or any other assistant.
Testing¶
Each application repository documents its own testing setup, and this page doesn't repeat it, because counts and commands there go stale the moment a suite grows:
New code is expected to arrive with tests written red/green — the failing test first, watched to fail for the right reason, then the minimum code to pass. For the mechanics of that cycle, see Working with Claude Code rather than this page.