@activatus/code-standards 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +12 -13
  2. package/docs/Guides/_category_.json +2 -2
  3. package/docs/Guides/migrating.md +33 -16
  4. package/docs/Guides/setup.md +46 -18
  5. package/docs/Standards/_category_.json +2 -2
  6. package/docs/Standards/agent-skills.md +29 -29
  7. package/docs/Standards/agent-specs.md +17 -32
  8. package/docs/Standards/direnv.mdx +8 -8
  9. package/docs/Standards/documentation.md +5 -2
  10. package/docs/Standards/editorconfig.md +23 -21
  11. package/docs/Standards/eslint.md +593 -402
  12. package/docs/Standards/human-readable-names.md +61 -21
  13. package/docs/Standards/lint-errors.md +37 -5
  14. package/docs/Standards/prettier.md +35 -26
  15. package/docs/Standards/readable-code.md +30 -0
  16. package/docs/Standards/stylelint.md +26 -11
  17. package/docs/Standards/styling.md +9 -3
  18. package/docs/Standards/tech-stack.md +3 -1
  19. package/docs/Structure/_category_.json +2 -2
  20. package/docs/Structure/component-organization.md +9 -2
  21. package/docs/Structure/folder-structure.md +26 -13
  22. package/docs/Structure/naming-conventions.md +0 -2
  23. package/docs/intro.md +1 -3
  24. package/docs/ontology.md +21 -26
  25. package/docs/templates.mdx +15 -38
  26. package/docs/version-history.md +133 -6
  27. package/package.json +6 -2
  28. package/scripts/renameSymbol.mjs +188 -0
  29. package/static/templates/.editorconfig +8 -11
  30. package/static/templates/AGENTS.md +16 -13
  31. package/static/templates/docs/development/coding-standards.md +4 -0
  32. package/static/templates/docsSite/docusaurus.config.mjs +144 -0
  33. package/static/templates/docsSite/sidebars.mjs +7 -0
  34. package/static/templates/docsSite/src/css/custom.css +6 -0
  35. package/static/templates/docsSite/tsconfig.json +5 -5
  36. package/static/templates/eslint/base/eslint.config.mjs +95 -70
  37. package/static/templates/eslint/nextjs/eslint.config.mjs +170 -126
  38. package/static/templates/eslint/react/eslint.config.mjs +160 -125
  39. package/static/templates/eslint/typescript/eslint.config.mjs +143 -115
  40. package/static/templates/globals.css +9 -9
  41. package/static/templates/next.config.mjs +13 -10
  42. package/static/templates/prettier.config.mjs +26 -0
  43. package/static/templates/stylelint/css/stylelint.config.mjs +37 -25
  44. package/static/templates/stylelint/scss/stylelint.config.mjs +10 -7
  45. package/docs/Standards/branch-naming.md +0 -66
  46. package/docs/Standards/conventional-commits.md +0 -189
  47. package/static/templates/.commitlintrc.json +0 -3
  48. package/static/templates/docsSite/docusaurus.config.ts +0 -119
  49. package/static/templates/docsSite/sidebars.ts +0 -8
  50. package/static/templates/husky/commit-msg +0 -1
  51. package/static/templates/prettier.config.js +0 -17
package/README.md CHANGED
@@ -56,6 +56,7 @@ The live site is at **[activatus-code-standards.vercel.app](https://activatus-co
56
56
  | `pnpm build` | 📦 Builds the static site into `build/` |
57
57
  | `pnpm serve` | 👀 Serves the built site so you can check it |
58
58
  | `pnpm typecheck` | 🔍 Runs TypeScript over the site config |
59
+ | `pnpm format` | ✨ Formats everything with Prettier |
59
60
 
60
61
  > 🔎 **Search only works on the built site.** Run `pnpm build` then `pnpm serve` if you want to test it. It won't show up in `pnpm start`, so don't go thinking you've broken it.
61
62
 
@@ -84,7 +85,7 @@ The full detail's on the site. This is the version you'd tell someone over a sch
84
85
  ### ✍️ Writing code
85
86
 
86
87
  - 📄 **No file over 300 lines.** If it's longer, it's doing two jobs. Split it. (Test files get a leave pass.)
87
- - 🗣️ **Every name is real English words.** Variables, props, form fields, types, files, folders, the lot. `button`, not `btn`. `library/`, not `lib/`. We're not paying by the letter. The one exception: names someone else owns, like Linear's `id` or Node's `cwd` option.
88
+ - 🗣️ **Every name is real English words.** Variables, props, form fields, types, files, folders, the lot. `button`, not `btn`. We're not paying by the letter. The one exception: names someone else owns, like Linear's `id` or Node's `cwd` option.
88
89
  - 🔒 **Always `const`.** Need `let`? Fine, but leave a comment saying why, or the linter knocks it back.
89
90
  - 🏹 **Arrow functions everywhere.** `const Button = () => {}`. The word `function` is clutter, so we don't use it.
90
91
  - 🔄 **No circular imports. Ever.** If two files import each other, pull the shared bit into a third file.
@@ -109,20 +110,18 @@ The full detail's on the site. This is the version you'd tell someone over a sch
109
110
  - 🔒 **`/docs` only exists when `DOCS_URL` is set.** It's never set in production, so the docs never leak onto a live site.
110
111
  - ✅ **Not finished until the docs are updated.** Change how something works, fix the doc in the same change.
111
112
 
112
- ### 🤖 AI agents
113
+ ### 🤖 Workflow is the project's call
113
114
 
114
- - 🛑 **Agents never commit code.** No commits, no pushes, no branches. They make the change, leave it sitting there, and a human reviews and commits it. Every time.
115
+ - 🧭 **Branches, commit messages, Pull Requests and whether AI agents may commit are up to each project.** Every team runs its work differently, so it goes in the project's own `AGENTS.md` and docs, not here. These standards are the base for the code itself.
115
116
 
116
- - 📦 **Third-party code is exempt.** Anything in `node_modules/` or `vendor/` isn't ours. Don't lint it, don't tidy it, leave it be.
117
-
118
- ### 🌿 Branches
117
+ ### 📦 Third-party code
119
118
 
120
- - 🏷️ **`type/short-description`**, in kebab-case: `feat/invoice-export`, `fix/login-redirect-loop`. Never work straight on `main`.
119
+ - 📦 **Third-party code is exempt.** Anything in `node_modules/` or `vendor/` isn't ours. Don't lint it, don't tidy it, leave it be.
121
120
 
122
121
  ### 🗂️ Structure
123
122
 
124
123
  - 🐫 **Code files are camelCase.** Components are PascalCase (`Button.tsx`) inside a camelCase folder (`button/`).
125
- - 🔗 **If it becomes a URL, it's kebab-case.** Route folders and doc files (`background-jobs.md`). CSS variables and branch names too.
124
+ - 🔗 **If it becomes a URL, it's kebab-case.** Route folders and doc files (`background-jobs.md`). CSS variables too.
126
125
  - 🧰 **Reusable functions live in `utils/`.** Global, section or component level, one folder per function, with an `index.ts` so imports stay tidy.
127
126
  - 📍 **Components live where they're used.** Design System Components in `components/ui/`, anything used on more than one page in `components/shared/`, and one-page components in that page's own `components/` folder. No feature folders.
128
127
  - 🧱 **Components follow the same order every time.** Imports, component, variables, state, effects, render. No inline functions in the render.
@@ -142,11 +141,11 @@ static/templates/
142
141
  ├── docsSite/ # 🌐 Docusaurus viewer that shows docs/ at /docs
143
142
  ├── eslint/ # 🚨 Four flavours: base, typescript, react, nextjs
144
143
  ├── stylelint/ # 💅 CSS and SCSS
145
- ├── prettier.config.js # ✨ Formatting
144
+ ├── prettier.config.mjs # ✨ Formatting
146
145
  ├── globals.css # 🎨 Tailwind + starter colour palette
147
146
  ├── .editorconfig # ⌨️ Editor whitespace rules
148
147
  ├── .nvmrc / .envrc # 🟢 Node version switching
149
- └── .commitlintrc.json # 📝 Commit message rules
148
+ └── husky/pre-commit # 🚦 Lint before every commit
150
149
  ```
151
150
 
152
151
  Copy them. Don't retype them. The ESLint ones have been run against real code, so they actually work, which is more than you can say for most configs floating around the internet.
@@ -165,8 +164,8 @@ Copy them. Don't retype them. The ESLint ones have been run against real code, s
165
164
  │ ├── images/ # 🖼️ Logo and favicon
166
165
  │ └── templates/ # 📋 The copy-paste files
167
166
  ├── src/css/custom.css # 🎨 Site theme overrides
168
- ├── docusaurus.config.ts # ⚙️ Site config
169
- └── sidebars.ts # 📑 Sidebar (builds itself from docs/)
167
+ ├── docusaurus.config.mjs # ⚙️ Site config
168
+ └── sidebars.mjs # 📑 Sidebar (builds itself from docs/)
170
169
  ```
171
170
 
172
171
  Built with [Docusaurus](https://docusaurus.io). The sidebar generates itself from the folders, so there's no menu file to forget about.
@@ -177,7 +176,7 @@ Built with [Docusaurus](https://docusaurus.io). The sidebar generates itself fro
177
176
 
178
177
  Reckon a rule's wrong, or there's one missing? Good. Standards that never change are standards nobody reads.
179
178
 
180
- 1. 🌿 **Branch off `main`**, named `type/short-description` (`docs/add-branch-naming`).
179
+ 1. 🌿 **Branch off `main`**, named after the ticket (`ACT-14-update-eslint-page`), or `type/short-description` if there's no ticket (`docs/update-eslint-page`).
181
180
  2. 📝 **Edit or add a Markdown file in `docs/`.** Name it in kebab-case (`naming-conventions.md`, not `namingConventions.md`), because the file name becomes the page's URL. Yes, we follow our own rules here.
182
181
  3. 📋 **Changing a config?** Edit the file in `static/templates/` and the matching page in `docs/Standards/` so the two don't drift apart.
183
182
  4. 🔢 **Add a version** to `docs/version-history.md`: what changed, and what a project has to do about it. Bump the major version in `package.json` to match (version 3 is `3.0.0`), and publish it to npm (npmjs.com) once it's merged. We use pnpm for everything, so that's `pnpm publish`, which lands in the same npm registry as `npm publish`. Projects read only the new versions, so if it's not in there, nobody hears about it.
@@ -1,4 +1,4 @@
1
1
  {
2
- "label": "Guides",
3
- "position": 5
2
+ "label": "Guides",
3
+ "position": 5
4
4
  }
@@ -25,7 +25,7 @@ Formatting changes are safe to land in one big PR because they don't change beha
25
25
  pnpm add -D prettier prettier-plugin-tailwindcss
26
26
  ```
27
27
 
28
- Add `prettier.config.js` — see the [Prettier page](/Standards/prettier) for the full file contents.
28
+ Add `prettier.config.mjs` — see the [Prettier page](/Standards/prettier) for the full file contents.
29
29
 
30
30
  Format everything at once:
31
31
 
@@ -33,7 +33,7 @@ Format everything at once:
33
33
  pnpm prettier --write .
34
34
  ```
35
35
 
36
- Commit with message `chore: apply prettier formatting`. This keeps the formatting diff isolated, making future `git blame` useful.
36
+ Commit it on its own, following the project's commit message format. This keeps the formatting diff isolated, making future `git blame` useful.
37
37
 
38
38
  Add a `.prettierignore` if you have generated files you don't want touched:
39
39
 
@@ -82,7 +82,7 @@ Before renaming anything, sort the short names into three piles:
82
82
  | ---------------------------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------------------------------------------------- |
83
83
  | **A dictionary word** — `id`, `docs`, `app`, `url`, `api` | Leave it | [Dictionary](/Standards/human-readable-names#dictionary) |
84
84
  | **A third-party name** — React's `ref`, Next.js's `params`, shadcn/ui's `cn`, Linear's `pageInfo`, Node's `cwd` option | Leave it exactly as it is | [Third-party names](/Standards/human-readable-names#third-party-names) |
85
- | **Our own shorthand** — `btn`, `props`, `lib/`, `utils/`, `inputRef` | Rename it | The [Never / Always](/Standards/human-readable-names#never--always) table |
85
+ | **Our own shorthand** — `btn`, `lib/`, `helpers/`, `utilities/` | Rename it | The [Never / Always](/Standards/human-readable-names#never--always) table |
86
86
 
87
87
  **Not sure which pile?** Don't guess and don't rename it. Ask, and if it is a dictionary word, [add it to the dictionary](/Standards/human-readable-names#adding-a-word-to-the-dictionary) first. Everyone then makes the same call.
88
88
 
@@ -90,16 +90,14 @@ Before renaming anything, sort the short names into three piles:
90
90
 
91
91
  These come up in nearly every project:
92
92
 
93
- | Before | After |
94
- | -------------------------------------- | ----------------------------------------------------- |
95
- | `lib/` | `library/` |
96
- | `utilities/`, `helpers/`, `helpers.ts` | `utils/`, or a file named after what it does |
97
- | `ButtonProperties`, `properties` | `ButtonProps`, `props` |
98
- | `inputRef` | `inputReference` (React's own `ref` prop stays `ref`) |
99
- | `MAX_`, `MIN_` | `MAXIMUM_`, `MINIMUM_` |
100
- | `"sm" \| "md" \| "lg"` | `"small" \| "medium" \| "large"` |
101
- | `auth`, `useAuth` | `authentication`, `useAuthentication` |
102
- | `(e) =>`, `(i) =>` | `(event) =>`, `(index) =>` |
93
+ | Before | After |
94
+ | -------------------------------------- | -------------------------------------------- |
95
+ | `utilities/`, `helpers/`, `helpers.ts` | `utils/`, or a file named after what it does |
96
+ | `ButtonProperties`, `properties` | `ButtonProps`, `props` |
97
+ | `MAX_`, `MIN_` | `MAXIMUM_`, `MINIMUM_` |
98
+ | `"sm" \| "md" \| "lg"` | `"small" \| "medium" \| "large"` |
99
+ | `auth`, `useAuth` | `authentication`, `useAuthentication` |
100
+ | `(e) =>`, `(i) =>` | `(event) =>`, `(index) =>` |
103
101
 
104
102
  `docs/`, `docsSite/`, `DOCS_URL` and `pnpm docs:dev` already follow the standard. Leave them.
105
103
 
@@ -107,7 +105,7 @@ These come up in nearly every project:
107
105
 
108
106
  1. **Folders**, with `git mv` so the history follows the files. Fix the imports in the same pull request.
109
107
  2. **Types**, so the `@typescript-eslint/naming-convention` errors clear.
110
- 3. **Variables, functions and properties.** Use your editor's **Rename Symbol** (F2), not find-and-replace: it renames every use and nothing else.
108
+ 3. **Variables, functions and properties.** Use your editor's **Rename Symbol** (F2), not find-and-replace: it renames every use and nothing else. An agent working from the command line has no editor, so it uses the [rename script](#renaming-from-the-command-line) instead.
111
109
  4. **Everything the linter can't see** — form fields, union values, routes, scripts, environment variables. Search for each one by hand.
112
110
 
113
111
  ### 4. Names that leave the codebase
@@ -121,6 +119,25 @@ Some names are used outside the code. Renaming them needs more than a code chang
121
119
 
122
120
  Write each of these up in the pull request so nobody gets caught out.
123
121
 
122
+ ### Renaming from the command line
123
+
124
+ An AI agent working in a terminal has no editor, so it cannot press F2. The package ships a script that does the same job, using the project's own TypeScript and the same rename engine as the editor:
125
+
126
+ ```bash
127
+ node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>
128
+ ```
129
+
130
+ ```bash
131
+ # Rename a type everywhere it is used
132
+ node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs components/ui/button/types.ts ButtonProperties ButtonProps
133
+ ```
134
+
135
+ - **Give it the file where the name is declared.** It renames that symbol and every use of it, across the whole project, and leaves anything else with the same name alone.
136
+ - **Shorthand stays correct.** `{ properties }` becomes `{ properties: props }`, so objects keep their shape.
137
+ - **It only renames TypeScript and JavaScript names.** Folders, files, form fields, routes and environment variables still need renaming by hand.
138
+ - **It cannot reach keys in plain object literals that aren't typed**, such as the expected value in a test's `toEqual({ properties: … })`. Search the tests for the old name and fix those keys by hand.
139
+ - **Run the type check and tests after each batch** of renames.
140
+
124
141
  ## Stage 5 — AGENTS.md
125
142
 
126
143
  Copy the [AGENTS.md template](/templates#agents) to the project root and replace every `[placeholder]`. Agree the standards with the person first ([Setup, step 3](/Guides/setup#3-agree-the-standards)), and set the code standards version from the [Version History](/version-history).
@@ -133,9 +150,9 @@ Copy the eight [standard skill files](/templates#skills) into `.agents/skills/`,
133
150
 
134
151
  Move the project's existing documentation into the standard [`docs/` folders](/Standards/documentation#-the-folders), rewriting each as a [Decision Doc](/Standards/documentation#-the-doc-format), then add the [`docsSite/` viewer](/Standards/documentation#-setting-it-up) so it shows at `/docs`.
135
152
 
136
- ## Stage 8 — Commit message checks
153
+ ## Stage 8 — Lint before every commit
137
154
 
138
- Add Commitlint and the two Husky hooks: one checks the commit message, the other runs `pnpm lint` before every commit. Add the lint hook **last**, once the project passes `pnpm lint`. See [Enforcing commit messages](/Standards/conventional-commits#enforcing-commit-messages).
155
+ Add the Husky hook that runs `pnpm lint` before every commit. Add it **last**, once the project passes `pnpm lint`. See [Lint before every commit](/Standards/lint-errors#lint-before-every-commit).
139
156
 
140
157
  ## Tips
141
158
 
@@ -9,12 +9,21 @@ sidebar_label: "Setup"
9
9
 
10
10
  The person creates the app themselves — with `create-next-app`, Expo or anything else — and tells you to follow the standards. **Do not ask which framework the project uses.** Look at the project: its `package.json` and files tell you. The person only answers the questions below and checks your work. They never run a command.
11
11
 
12
+ **These standards are the base, for code only.** A project builds on top of them: it can add its own folders and conventions, and it makes its own project-management decisions (tickets, statuses, releases, who commits). Those go in the project's own docs, not here.
13
+
12
14
  ## 1. Install the standards
13
15
 
14
16
  ```bash
15
17
  pnpm add -D @activatus/code-standards
16
18
  ```
17
19
 
20
+ **If pnpm refuses because the version is too new**, that is pnpm's `minimumReleaseAge` setting: by default it will not install a version published less than a day ago. The standards come from us, so add the package to `minimumReleaseAgeExclude` in `pnpm-workspace.yaml`:
21
+
22
+ ```yaml title="pnpm-workspace.yaml"
23
+ minimumReleaseAgeExclude:
24
+ - "@activatus/code-standards"
25
+ ```
26
+
18
27
  The standards are now in `node_modules/@activatus/code-standards/`:
19
28
 
20
29
  | Folder | What it holds |
@@ -54,56 +63,56 @@ Tell me the numbers to skip or change, or say "all good".
54
63
  9. EditorConfig
55
64
  10. Node version set by .nvmrc and direnv
56
65
  11. Styling: Tailwind, flexbox first, colours only from the global palette
57
- 12. Folder structure: folders at the project root, functions in utils/
66
+ 12. Folder structure: folders at the project root; reusable helper functions in utils/ (no business rules, no outside calls)
58
67
  13. Components live where they are used: components/ui/, components/shared/, or beside their page
59
68
  14. Component files in a fixed order, with index.ts exports, and server and client code in separate files
60
69
  15. Design System Components: every project builds the standard components with the same props
61
70
  16. Imports: no circular imports, import from folders not files
62
71
  17. API routes: one folder per route, kebab-case
63
72
  18. Docs: every file in docs/ is a Decision Doc, shown at /docs by the docs site
64
- 19. Conventional Commits, checked by Husky, with pnpm lint before every commit
65
- 20. Branch names: type/short-description
66
- 21. AGENTS.md and the eight agent skills
67
- 22. AI agents never commit, push or make branches (strict no commit)
68
- 23. The Ontology: the shared words for code
73
+ 19. Lint before every commit: a Husky hook runs pnpm lint
74
+ 20. AGENTS.md and the eight agent skills
75
+ 21. The Ontology: the shared words for code
69
76
  ```
70
77
 
71
78
  Then wait for the answer.
72
79
 
73
- | The person says | Do |
74
- | --------------------------------------------------------- | ----------------------------- |
75
- | "All good" | Apply every standard |
76
- | "Skip 7" | Apply every standard except 7 |
77
- | "Change 22: agents can commit when I say I'm on my phone" | Apply 22 as they describe it |
78
- | Something unclear | Ask. Do not guess |
80
+ | The person says | Do |
81
+ | --------------------------------------- | ----------------------------- |
82
+ | "All good" | Apply every standard |
83
+ | "Skip 7" | Apply every standard except 7 |
84
+ | "Change 7: we use Biome for formatting" | Apply 7 as they describe it |
85
+ | Something unclear | Ask. Do not guess |
79
86
 
80
87
  **Record the answer** in `docs/development/coding-standards.md`, under "Details". For each skipped or changed standard, write its number, its name, what is different, and the reason the person gave. If nothing is different, write "No differences". Copy the file from `static/templates/docs/development/coding-standards.md` if it does not exist.
81
88
 
82
- If standard 22 is changed, also replace the "NEVER COMMIT CODE" lines in `AGENTS.md` with the person's rule. See [A project can choose otherwise](/Standards/agent-specs#a-project-can-choose-otherwise).
89
+ The list has nothing about branches, commit messages or whether agents may commit. Those are the project's own workflow. Ask the person how they work, and write it in the "Project workflow" section of `AGENTS.md`. See [Project workflow](/Standards/agent-specs#project-workflow).
83
90
 
84
91
  ## 4. Apply the standards
85
92
 
86
93
  Do only the standards the person agreed to. Copy every file from `node_modules/@activatus/code-standards/static/templates/` — never write a config file from scratch.
87
94
 
95
+ **Every config file is `.mjs`, even in a TypeScript project.** Never convert one to `.ts` or `.mts`. `.mjs` works in both, so every project looks the same. If the project has a config as `.js`, `.ts` or `.mts`, such as `next.config.ts` from `create-next-app` or `vitest.config.mts`, rename it to `.mjs`, removing any TypeScript-only syntax: a type annotation becomes a JSDoc comment, for example `/** @type {import("next").NextConfig} */`. A tool that cannot read `.mjs` keeps its own format.
96
+
88
97
  **An existing project with code already in it** also needs its code brought up to the standards. Do that with [Migrating an Existing Project](/Guides/migrating), one stage per pull request, after the config files below are in place.
89
98
 
90
99
  | Standard | What to set up |
91
100
  | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
92
101
  | 6. ESLint | Copy the config for the project's framework from `static/templates/eslint/`: `base`, `typescript`, `react` or `nextjs`. Install the packages listed on the [ESLint page](/Standards/eslint). Add the scripts `"lint": "eslint ."` and `"lint:fix": "eslint . --fix"` |
93
- | 7. Prettier | `pnpm add -D prettier prettier-plugin-tailwindcss`. Copy `static/templates/prettier.config.js`. Add the scripts `"format": "prettier --write ."` and `"format:check": "prettier --check ."` |
102
+ | 7. Prettier | `pnpm add -D prettier prettier-plugin-tailwindcss`. Copy `static/templates/prettier.config.mjs`. Add the scripts `"format": "prettier --write ."` and `"format:check": "prettier --check ."` |
94
103
  | 8. Stylelint | Only if the project has hand-written CSS or SCSS. Copy the config from `static/templates/stylelint/css/` or `scss/`. See [Stylelint](/Standards/stylelint) |
95
104
  | 9. EditorConfig | Copy `static/templates/.editorconfig` |
96
105
  | 10. Node version | Copy `static/templates/.nvmrc` and `static/templates/.envrc`. See [direnv + nvm](/Standards/direnv) |
97
106
  | 11. Styling | Copy `static/templates/globals.css` to `app/globals.css`. Ask the person for the project's colours, and replace the example palette |
98
107
  | 18. Docs | Copy `static/templates/docs/` to `docs/` and `static/templates/docsSite/` to `docsSite/`. Add the `/docs` route from `static/templates/next.config.mjs`. See [Setting it up](/Standards/documentation#-setting-it-up) |
99
- | 19. Commits | Copy `static/templates/.commitlintrc.json` and the two hooks in `static/templates/husky/`. Add the lint hook last, once `pnpm lint` passes. See [Enforcing commit messages](/Standards/conventional-commits#enforcing-commit-messages) |
100
- | 21. AGENTS.md and skills | Copy `static/templates/AGENTS.md` to the project root and fill in every `[placeholder]`. If the framework wrote its own `AGENTS.md` (Next.js does), keep any instruction it gives about reading the framework's own docs. Copy `static/templates/skills/` into `.agents/skills/`, and again into `.claude/commands/` |
108
+ | 19. Lint before commit | Copy `static/templates/husky/pre-commit` to `.husky/pre-commit`, once `pnpm lint` passes. See [Lint before every commit](/Standards/lint-errors#lint-before-every-commit) |
109
+ | 20. AGENTS.md and skills | Copy `static/templates/AGENTS.md` to the project root and fill in every `[placeholder]`. If the framework wrote its own `AGENTS.md` (Next.js does), keep any instruction it gives about reading the framework's own docs. Copy `static/templates/skills/` into `.agents/skills/`, and again into `.claude/commands/` |
101
110
 
102
111
  The other standards are rules for how code is written. There is nothing to install for them: follow them in every change.
103
112
 
104
113
  **Finish by:**
105
114
 
106
- 1. Setting `**Code standards version:**` in `AGENTS.md` to the installed package's major version.
115
+ 1. Setting `**Code standards version:**` in `AGENTS.md` to the installed package's major version. See [Finishing a change later](#finishing-a-change-later) if anything is left to do.
107
116
  2. Running `pnpm lint`, `pnpm format:check` and the tests.
108
117
  3. Telling the person what you set up, which standards they skipped, and anything only they can do, such as filling in a secret in `.env.local`.
109
118
 
@@ -125,6 +134,25 @@ The project already follows the standards, and a newer version is out.
125
134
  3. **Read `node_modules/@activatus/code-standards/docs/version-history.md`**, but only the versions newer than the project's. Do not re-read the rest of the standards.
126
135
  4. **Skip any change to a standard the project opted out of.** The opt-outs are listed in `docs/development/coding-standards.md`.
127
136
  5. **Do every other change** as its "What to do" says, and run its "How to check" search. One pull request per kind of change.
128
- 6. **Set `**Code standards version:**`** in `AGENTS.md` to the new version, and tell the person what changed.
137
+ 6. **Set `**Code standards version:**`** in `AGENTS.md` to the new version, and tell the person what changed. If a change is being finished later, record it first: see [Finishing a change later](#finishing-a-change-later).
129
138
 
130
139
  See the [Version History](/version-history) for the full update rules.
140
+
141
+ ---
142
+
143
+ ## Finishing a change later
144
+
145
+ Sometimes a change is too big for the update, such as switching on the standard ESLint config in a project that never had it. It can be done later in its own Pull Request, but **the version number must stay honest**.
146
+
147
+ 1. Set the project's version to the new version anyway.
148
+ 2. In `docs/development/coding-standards.md`, under **Unfinished changes**, list each change that is not done yet: its version and number, what is left, and where it is being done (a ticket or a Pull Request).
149
+
150
+ ```md
151
+ ## Unfinished changes
152
+
153
+ - Version 2, change 4: the standard ESLint config is not switched on yet. Being done in ACT-120.
154
+ ```
155
+
156
+ 3. When it is finished, remove it from the list.
157
+
158
+ An agent updating to a later version reads this list first, and finishes or skips those changes before starting the new ones.
@@ -1,4 +1,4 @@
1
1
  {
2
- "label": "Standards",
3
- "position": 6
2
+ "label": "Standards",
3
+ "position": 6
4
4
  }
@@ -12,10 +12,10 @@ Skills are shared, versioned, and executed with real tool access. A vague one wa
12
12
 
13
13
  One canonical copy, one mirror:
14
14
 
15
- | Path | Role |
16
- | --- | --- |
17
- | `.agents/skills/*.md` | **Canonical.** Portable location any compatible agent reads. The only copy you edit. |
18
- | `.claude/commands/*.md` | Claude Code mirror, exposed as `/name`. |
15
+ | Path | Role |
16
+ | ----------------------- | ------------------------------------------------------------------------------------ |
17
+ | `.agents/skills/*.md` | **Canonical.** Portable location any compatible agent reads. The only copy you edit. |
18
+ | `.claude/commands/*.md` | Claude Code mirror, exposed as `/name`. |
19
19
 
20
20
  Keep the mirror identical to the canonical copy — edit the skill in `.agents/skills/`, then copy it across.
21
21
 
@@ -40,14 +40,14 @@ allowed-tools: Read, Glob, Grep, Bash(pnpm lint:*), Bash(eslint:*)
40
40
  Run all configured linters and report issues without modifying any files.
41
41
  ```
42
42
 
43
- | Field | Required | Purpose |
44
- | --- | --- | --- |
45
- | `name` | Yes | The invocation name, in camelCase. Must match the filename. |
46
- | `description` | Yes | One line, **under 60 characters**. How an agent decides to use it. |
47
- | `argument-hint` | If it takes arguments | Shown during autocomplete. |
48
- | `allowed-tools` | Strongly encouraged | The tools the skill may use. See below. |
49
- | `model` | No | Pin only for genuinely mechanical skills. |
50
- | `disable-model-invocation` | No | Set when a skill must only ever be run by a human. |
43
+ | Field | Required | Purpose |
44
+ | -------------------------- | --------------------- | ------------------------------------------------------------------ |
45
+ | `name` | Yes | The invocation name, in camelCase. Must match the filename. |
46
+ | `description` | Yes | One line, **under 60 characters**. How an agent decides to use it. |
47
+ | `argument-hint` | If it takes arguments | Shown during autocomplete. |
48
+ | `allowed-tools` | Strongly encouraged | The tools the skill may use. See below. |
49
+ | `model` | No | Pin only for genuinely mechanical skills. |
50
+ | `disable-model-invocation` | No | Set when a skill must only ever be run by a human. |
51
51
 
52
52
  Quote any `argument-hint` that starts with `[`, or YAML parses it as a list:
53
53
 
@@ -60,20 +60,20 @@ argument-hint: [path] # a one-element array — wrong
60
60
 
61
61
  Prose like "this skill is read-only" is a request. `allowed-tools` is the enforcement. Whatever a skill's body promises not to do, the allowlist should make impossible:
62
62
 
63
- | The skill says | So the allowlist omits |
64
- | --- | --- |
65
- | "Do NOT make file changes" | `Edit`, `Write` |
66
- | "Do NOT auto-fix" | `Edit`, `Write` |
67
- | "Do NOT stage or commit" | every `Bash(git …)` |
68
- | "Do NOT push" | `Bash(git push:*)` |
63
+ | The skill says | So the allowlist omits |
64
+ | -------------------------- | ---------------------- |
65
+ | "Do NOT make file changes" | `Edit`, `Write` |
66
+ | "Do NOT auto-fix" | `Edit`, `Write` |
67
+ | "Do NOT stage or commit" | every `Bash(git …)` |
68
+ | "Do NOT push" | `Bash(git push:*)` |
69
69
 
70
70
  Three rules follow from this:
71
71
 
72
72
  1. **Every command the body tells the agent to run must be allowlisted.** A body that says `eslint $ARGUMENTS` under an allowlist of only `Bash(pnpm exec eslint:*)` blocks itself halfway through. List each form the body actually uses.
73
73
  2. **Grant the narrowest set that still works.** `Bash(pnpm lint:*), Bash(eslint:*)` over a bare `Bash`.
74
- 3. **Never grant `git commit` or `git push`.** [Agents never commit code](/Standards/agent-specs#agents-never-commit-code), so no skill is allowed to.
74
+ 3. **Never grant `git commit` or `git push`.** A skill does one job and leaves its changes for whoever ran it. Committing is the [project's workflow](/Standards/agent-specs#project-workflow), not a skill's.
75
75
 
76
- Be honest about the limit: patterns gate the command, not its flags. `Bash(eslint:*)` still permits `eslint --fix`. The allowlist reliably prevents a skill from reaching for a whole *category* of tool; keep the prose instruction as well for anything finer.
76
+ Be honest about the limit: patterns gate the command, not its flags. `Bash(eslint:*)` still permits `eslint --fix`. The allowlist reliably prevents a skill from reaching for a whole _category_ of tool; keep the prose instruction as well for anything finer.
77
77
 
78
78
  ## Write for the agent, not the user
79
79
 
@@ -114,12 +114,12 @@ Respect the project's own scripts. `pnpm lint` picks up workspace configuration
114
114
 
115
115
  Before merging a skill:
116
116
 
117
- - [ ] `name` matches the filename
118
- - [ ] `description` is one line, under 60 characters
119
- - [ ] `argument-hint` present if it takes arguments, and quoted if it starts with `[`
120
- - [ ] `allowed-tools` omits everything the body promises not to do
121
- - [ ] `allowed-tools` includes every command the body does invoke
122
- - [ ] Body is written as instructions to the agent
123
- - [ ] Sub-steps indented three spaces
124
- - [ ] Prettier leaves the file unchanged
125
- - [ ] `.claude/commands/` mirror matches `.agents/skills/`
117
+ - [ ] `name` matches the filename
118
+ - [ ] `description` is one line, under 60 characters
119
+ - [ ] `argument-hint` present if it takes arguments, and quoted if it starts with `[`
120
+ - [ ] `allowed-tools` omits everything the body promises not to do
121
+ - [ ] `allowed-tools` includes every command the body does invoke
122
+ - [ ] Body is written as instructions to the agent
123
+ - [ ] Sub-steps indented three spaces
124
+ - [ ] Prettier leaves the file unchanged
125
+ - [ ] `.claude/commands/` mirror matches `.agents/skills/`
@@ -7,26 +7,11 @@ sidebar_label: "AGENTS.md"
7
7
 
8
8
  Every Activatus repository must have an `AGENTS.md` in its root. This file gives AI coding agents (Claude Code, Copilot, Cursor, etc.) the context they need to work effectively without repeated explanation.
9
9
 
10
- ## Agents never commit code
10
+ ## Project workflow
11
11
 
12
- **An AI agent never commits.** It does not run `git commit`, `git push`, `git merge`, `git rebase` or `git stash`, and it does not create, switch or delete branches.
12
+ **How a project runs its work is not part of these standards.** Branch names, commit messages, Pull Requests, merging, releases, and whether AI agents may commit, push or make branches are all the project's own decisions. Every project makes them differently.
13
13
 
14
- The agent makes the changes, leaves them uncommitted in the working tree, and says what it changed. A person reviews the changes and commits them.
15
-
16
- Every `AGENTS.md` states this at the very top and again under "Out of scope for AI agents". The [template](/templates#agents) already does.
17
-
18
- ### A project can choose otherwise
19
-
20
- **Strict no commit is the default.** It is standard 22 in the list the person agrees to during [Setup](/Guides/setup#3-agree-the-standards), so they can change it then. Or they can be asked directly:
21
-
22
- > Should AI agents be allowed to commit in this project, or is it strict no commit?
23
-
24
- | Answer | What goes in `AGENTS.md` |
25
- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
26
- | **Strict no commit** (the default) | The template as it is |
27
- | **Agents may commit** | Replace the "NEVER COMMIT CODE" lines with the project's own rule, saying exactly which agents may commit, push and open Pull Requests, and when. A tool built to ship code with AI, such as Launchpad, chooses this |
28
-
29
- A person can also allow it for one piece of work, such as when they are away from their computer. That permission lasts for that piece of work only, and never changes the project's rule.
14
+ Each project writes them up in its own docs, usually in `docs/development/`, and its `AGENTS.md` has a **Project workflow** section that points to them and states the rules an agent must follow. The most important one goes first: whether an agent may commit.
30
15
 
31
16
  ## Template
32
17
 
@@ -36,19 +21,19 @@ Start from the [AGENTS.md template](/templates#agents) and replace every `[place
36
21
 
37
22
  Every `AGENTS.md` must include these sections. Monorepos (`pnpm-workspace.yaml`, Turborepo, Nx, etc.) also require a **Workspace packages** table listing each package, its path and a one-line description.
38
23
 
39
- | Section | Purpose |
40
- | -------------------------- | ----------------------------------------------------------------------------------------- |
41
- | Project overview | One paragraph: what it does, who uses it, why it exists |
42
- | Repository layout | Directory tree at depth 2 |
43
- | Tech stack | Language, runtime, framework, database, infra (with versions) |
44
- | Essential commands | Install, dev, build, test, lint, type-check |
45
- | Development workflow | [Branch naming](/Standards/branch-naming), commit format, PR requirements, merge strategy |
46
- | Environment variables | All required and optional env vars with descriptions |
47
- | Ontology | Link to the [ontology](/ontology), and the instruction to read it and use its terms |
48
- | Documentation | Where the project's docs are, and the instruction to read them before starting work |
49
- | Code standards | Link to these standards and the rules agents must follow in every change |
50
- | Available skills | Table of the agent skills the project provides |
51
- | Out of scope for AI agents | Explicit list of forbidden agent actions — always including "never commit code" |
24
+ | Section | Purpose |
25
+ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
26
+ | Project overview | One paragraph: what it does, who uses it, why it exists |
27
+ | Repository layout | Directory tree at depth 2 |
28
+ | Tech stack | Language, runtime, framework, database, infra (with versions) |
29
+ | Essential commands | Install, dev, build, test, lint, type-check |
30
+ | Project workflow | The project's own rules for branches, commits, Pull Requests and merging, and whether agents may commit. Points to where they are written up |
31
+ | Environment variables | All required and optional env vars with descriptions |
32
+ | Ontology | Link to the [ontology](/ontology), and the instruction to read it and use its terms |
33
+ | Documentation | Where the project's docs are, and the instruction to read them before starting work |
34
+ | Code standards | Link to these standards and the rules agents must follow in every change |
35
+ | Available skills | Table of the agent skills the project provides |
36
+ | Out of scope for AI agents | Explicit list of what agents must not do in this project |
52
37
 
53
38
  ## Standard skills
54
39
 
@@ -67,7 +52,7 @@ Every project provides these eight skills. **The files are ready to copy from th
67
52
 
68
53
  Skill files are named in camelCase (`lintFix.md`), so the invocation is camelCase too (`/lintFix`). They are not documentation pages and have no URL, so the kebab-case rule for docs does not apply.
69
54
 
70
- No skill commits code — see [Agents never commit code](#agents-never-commit-code).
55
+ No skill commits, pushes or makes branches. A skill does one job and leaves its changes for the agent or person who ran it. Whether those changes are then committed is the [project's workflow](#project-workflow).
71
56
 
72
57
  ### Skill locations
73
58
 
@@ -10,9 +10,9 @@ Automatically switch to the project's Node.js version when you `cd` into the rep
10
10
 
11
11
  Two files work together:
12
12
 
13
- | File | Purpose |
14
- | --- | --- |
15
- | `.nvmrc` | Declares the required Node.js major version (e.g. `20`) |
13
+ | File | Purpose |
14
+ | -------- | ------------------------------------------------------------------------ |
15
+ | `.nvmrc` | Declares the required Node.js major version (e.g. `20`) |
16
16
  | `.envrc` | Loaded by direnv on `cd`; sources nvm and activates the declared version |
17
17
 
18
18
  When you enter the project directory direnv runs `.envrc`, which installs the declared Node version (if missing) and activates it for your shell session. Leaving the directory restores the previous environment automatically.
@@ -207,11 +207,11 @@ fi
207
207
 
208
208
  The script handles four environments:
209
209
 
210
- | Environment | How nvm is loaded |
211
- | --- | --- |
212
- | macOS — manual install | `$HOME/.nvm/nvm.sh` sourced directly |
213
- | macOS — Homebrew | `$(brew --prefix nvm)/nvm.sh` sourced as fallback |
214
- | Linux / WSL 2 | `$HOME/.nvm/nvm.sh` sourced directly |
210
+ | Environment | How nvm is loaded |
211
+ | -------------------------------- | --------------------------------------------------------------- |
212
+ | macOS — manual install | `$HOME/.nvm/nvm.sh` sourced directly |
213
+ | macOS — Homebrew | `$(brew --prefix nvm)/nvm.sh` sourced as fallback |
214
+ | Linux / WSL 2 | `$HOME/.nvm/nvm.sh` sourced directly |
215
215
  | Windows — Git Bash + nvm-windows | `nvm` is already in `PATH` as an executable; no sourcing needed |
216
216
 
217
217
  The version is read explicitly from `.nvmrc` (stripping whitespace) and passed to both `nvm install` and `nvm use`, making the script compatible with both nvm and nvm-windows.
@@ -247,7 +247,10 @@ const nextConfig = {
247
247
 
248
248
  return [
249
249
  { source: "/docs", destination: `${DOCS_URL}/docs/` },
250
- { source: "/docs/:path*", destination: `${DOCS_URL}/docs/:path*` },
250
+ {
251
+ source: "/docs/:path*",
252
+ destination: `${DOCS_URL}/docs/:path*`,
253
+ },
251
254
  ];
252
255
  },
253
256
  };
@@ -261,7 +264,7 @@ export default nextConfig;
261
264
 
262
265
  1. **Copy the docs.** Copy the [`docs/` templates](/templates#document-templates) into the project's `docs/` folder. Rename `overview/what-is-it.md` after the project (`what-is-launchpad.md`) and update its title.
263
266
 
264
- 2. **Copy the viewer.** Copy the [`docsSite/` template](/templates#docs-site) into the project root. Rename `package.json.txt` to `package.json` and `gitignore.txt` to `.gitignore`, set `PROJECT_NAME` in `docusaurus.config.ts`, and point the home redirect in `src/pages/index.tsx` at the renamed overview file.
267
+ 2. **Copy the viewer.** Copy the [`docsSite/` template](/templates#docs-site) into the project root. Rename `package.json.txt` to `package.json` and `gitignore.txt` to `.gitignore`, set `PROJECT_NAME` in `docusaurus.config.mjs`, and point the home redirect in `src/pages/index.tsx` at the renamed overview file.
265
268
 
266
269
  3. **Add the route.** Add the rewrite above to `next.config.mjs`.
267
270