AGENTS.md, under Shared with the other kanso-labs repositories, because an agent handed one repository reads that file and never sees the others. The canonical text is CONVENTIONS.md in kanso-labs/.github.
The shared set
Keys in JSON and YAML are ordered by name
Keys in JSON and YAML are ordered by name
Files whose order carries meaning are exempt: workflows, where step order is execution order; changelogs, which are chronological; and
package.json, where the npm ecosystem expects name and version first.In TypeScript the same rule is enforced rather than trusted: the Node repositories run eslint-plugin-perfectionist at recommended-natural, so object keys, imports and union members are sorted by the linter.A workflow's filename is the kebab-case of its name
A workflow's filename is the kebab-case of its name
name: Release Please lives in release-please.yaml. Reusable workflows, meaning those triggered only by workflow_call, take a leading underscore, so _publish-npm.yaml sits apart from the entry points in a folder listing. The extension is .yaml everywhere, apart from files a tool only finds under .yml, such as codecov.yml.Job names and step names are imperative verb phrases
Job names and step names are imperative verb phrases
Build, Run the unit tests, Publish to npm. Job ids, step ids and matrix keys are exempt, since renaming them means updating every needs and steps reference for no visible benefit.A job name is also a check name, and a ruleset requiring checks matches them by exact string. Renaming a job means renaming it in the ruleset in the same change.Dependency versions are pinned exactly
Dependency versions are pinned exactly
Every
dependencies, devDependencies and optionalDependencies entry is a bare version, 1.2.3, never ^1.2.3, ~1.2.3, >=1.2.3, *, 1.x or an || union. Renovate opens those bumps too, so a release that changes something arrives as a pull request you can read rather than a surprise on the next install.peerDependencies are the deliberate exception. They state what the consumer’s own installed copy must satisfy, so ranges are correct there and stay..tool-versions pins a fully specified version on every line
.tool-versions pins a fully specified version on every line
nodejs 24.21.0, never nodejs 24 or nodejs lts.Read the version from the file
The.tool-versions rule reaches further than it looks. The shared setup-node action reads node-version-file from .tool-versions by default, so that file is what every CI run resolves. A version written into prose beside it goes stale on the next Renovate bump while the pin moves on, so a command that needs the version reads it out of the file:
package-lock.json as it installs, in a way no check can see, so installing under the pinned Node is what keeps the lockfile honest.
Formatting is not shared
Assuming it is will send you to a command that does not exist. Each repository says what it runs under Commands in itsAGENTS.md:
LICENSE.md is exempt everywhere, since it is the organization’s licence and stays byte-identical in every repository. Changelogs that release-please writes are exempt too, because formatting one only holds until the next release pull request rewrites it.
Changing a convention
Nothing enforces the copies, deliberately: the organization decided a checker was not worth what it would catch. So a change to the shared set is a change to every copy, and the discipline is the only thing holding them together.1
Edit CONVENTIONS.md first
It is the copy that is right by definition.
2
Open a pull request per repository
Each carries the same edit to its
AGENTS.md. A copy that has drifted is wrong not because it disagrees with a checker, but because the next agent to read it will follow it.Commits and releases
How a pull request title becomes a version, a changelog line and a release.

