@activatus/code-standards 2.0.0 → 3.0.1

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 (52) hide show
  1. package/README.md +12 -14
  2. package/docs/Guides/_category_.json +2 -2
  3. package/docs/Guides/migrating.md +50 -25
  4. package/docs/Guides/setup.md +52 -17
  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 +62 -22
  13. package/docs/Standards/lint-errors.md +3 -7
  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 -2
  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 +12 -49
  26. package/docs/version-history.md +143 -10
  27. package/package.json +6 -2
  28. package/scripts/renameSymbol.mjs +230 -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/husky/pre-commit +0 -1
  52. 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,10 @@ 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
- ├── .nvmrc / .envrc # 🟢 Node version switching
149
- └── .commitlintrc.json # 📝 Commit message rules
147
+ └── .nvmrc / .envrc # 🟢 Node version switching
150
148
  ```
151
149
 
152
150
  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 +163,8 @@ Copy them. Don't retype them. The ESLint ones have been run against real code, s
165
163
  │ ├── images/ # 🖼️ Logo and favicon
166
164
  │ └── templates/ # 📋 The copy-paste files
167
165
  ├── src/css/custom.css # 🎨 Site theme overrides
168
- ├── docusaurus.config.ts # ⚙️ Site config
169
- └── sidebars.ts # 📑 Sidebar (builds itself from docs/)
166
+ ├── docusaurus.config.mjs # ⚙️ Site config
167
+ └── sidebars.mjs # 📑 Sidebar (builds itself from docs/)
170
168
  ```
171
169
 
172
170
  Built with [Docusaurus](https://docusaurus.io). The sidebar generates itself from the folders, so there's no menu file to forget about.
@@ -177,7 +175,7 @@ Built with [Docusaurus](https://docusaurus.io). The sidebar generates itself fro
177
175
 
178
176
  Reckon a rule's wrong, or there's one missing? Good. Standards that never change are standards nobody reads.
179
177
 
180
- 1. 🌿 **Branch off `main`**, named `type/short-description` (`docs/add-branch-naming`).
178
+ 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
179
  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
180
  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
181
  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
  }
@@ -4,7 +4,7 @@ sidebar_position: 3
4
4
 
5
5
  # Migrating an Existing Project
6
6
 
7
- Migrating an established codebase to the shared standards is best done in stages to keep PRs reviewable.
7
+ Migrating an established codebase to the shared standards is best done in stages, so each change stays small enough to check properly.
8
8
 
9
9
  **Already following the standards, and just updating to a newer version?** You don't need this whole guide. Read the [Version History](/version-history) from your project's version onward, and do only what it lists.
10
10
 
@@ -19,13 +19,13 @@ The standards apply to **code we write**, not to packages we pull in. Do not lin
19
19
 
20
20
  ## Stage 1 — Prettier (formatting only)
21
21
 
22
- Formatting changes are safe to land in one big PR because they don't change behaviour.
22
+ Formatting changes are safe to make all at once because they don't change behaviour.
23
23
 
24
24
  ```bash
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
+ Keep the reformat apart from any other change, so the formatting is easy to tell apart from real changes later.
37
37
 
38
38
  Add a `.prettierignore` if you have generated files you don't want touched:
39
39
 
@@ -68,7 +68,7 @@ export default [
68
68
  ];
69
69
  ```
70
70
 
71
- Run `pnpm lint` and triage the output. Fix issues in thematic PRs (e.g. all `any` removals together). Once clean, remove the overrides.
71
+ Run `pnpm lint` and triage the output. Fix them one kind at a time (for example, all `any` removals together). Once clean, remove the overrides.
72
72
 
73
73
  ## Stage 4 — Names
74
74
 
@@ -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,24 +90,22 @@ 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
 
106
- ### 3. Rename in this order, one pull request each
104
+ ### 3. Rename in this order
107
105
 
108
- 1. **Folders**, with `git mv` so the history follows the files. Fix the imports in the same pull request.
106
+ 1. **Folders**, with `git mv` so the history follows the files. Fix the imports at the same time.
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
@@ -119,7 +117,38 @@ Some names are used outside the code. Renaming them needs more than a code chang
119
117
  - **API routes and request fields** used by another app need both names to work until that app is updated.
120
118
  - **Routes people have bookmarked** need a redirect from the old path.
121
119
 
122
- Write each of these up in the pull request so nobody gets caught out.
120
+ Tell the person about each of these, so nobody gets caught out.
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
+ **Many renames at once:** list them in a text file, one per line, and pass it with `--list`. Blank lines and lines starting with `#` are skipped, and the renames run in order:
136
+
137
+ ```text title="renames.txt"
138
+ # Version 3 renames
139
+ components/ui/button/types.ts ButtonProperties ButtonProps
140
+ lib/terminal/tabs.ts surfaceReference surfaceRef
141
+ ```
142
+
143
+ ```bash
144
+ node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs --list renames.txt
145
+ ```
146
+
147
+ - **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.
148
+ - **Shorthand stays correct.** `{ properties }` becomes `{ properties: props }`, so objects keep their shape.
149
+ - **It only renames TypeScript and JavaScript names.** Folders, files, form fields, routes and environment variables still need renaming by hand.
150
+ - **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.
151
+ - **Run the type check and tests after each batch** of renames.
123
152
 
124
153
  ## Stage 5 — AGENTS.md
125
154
 
@@ -133,12 +162,8 @@ Copy the eight [standard skill files](/templates#skills) into `.agents/skills/`,
133
162
 
134
163
  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
164
 
136
- ## Stage 8 — Commit message checks
137
-
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).
139
-
140
165
  ## Tips
141
166
 
142
- - **Don't mix formatting and logic changes** in the same PR.
167
+ - **Don't mix formatting and logic changes.** Reformat on its own, then change the code.
143
168
  - **Exclude generated files** from ESLint with `// eslint-disable-file` or `.eslintignore`-equivalent glob ignores in the config.
144
169
  - **Fix new-file compliance first**: agree that all _new_ files must pass the full ruleset even before the migration is complete.
@@ -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,63 @@ 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
73
+ 19. Removed in version 3: commit messages are the project's own workflow
74
+ 20. Removed in version 3: branch names are the project's own workflow
66
75
  21. AGENTS.md and the eight agent skills
67
- 22. AI agents never commit, push or make branches (strict no commit)
76
+ 22. Removed in version 3: whether agents commit is the project's own workflow
68
77
  23. The Ontology: the shared words for code
69
78
  ```
70
79
 
71
80
  Then wait for the answer.
72
81
 
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 |
82
+ **The numbers never change.** A project records its choices by number, so the numbers stay put:
83
+
84
+ - **A number is never reused.** A removed standard keeps its number in the list, marked "Removed in version N", so a project's old choices still point at the right thing.
85
+ - **A new standard takes the number of the standard it sits closest to, plus a decimal:** a new styling standard after 11 is 11.1, then 11.2, up to 11.9. The list stays short, and nothing after it moves.
86
+ - **Skip the removed ones** when applying the standards. There is nothing to do for them.
87
+
88
+ | The person says | Do |
89
+ | --------------------------------------- | ----------------------------- |
90
+ | "All good" | Apply every standard |
91
+ | "Skip 7" | Apply every standard except 7 |
92
+ | "Change 7: we use Biome for formatting" | Apply 7 as they describe it |
93
+ | Something unclear | Ask. Do not guess |
79
94
 
80
95
  **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
96
 
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).
97
+ 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
98
 
84
99
  ## 4. Apply the standards
85
100
 
86
101
  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
102
 
88
- **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.
103
+ **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.
104
+
105
+ **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 at a time, after the config files below are in place.
89
106
 
90
107
  | Standard | What to set up |
91
108
  | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
92
109
  | 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 ."` |
110
+ | 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
111
  | 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
112
  | 9. EditorConfig | Copy `static/templates/.editorconfig` |
96
113
  | 10. Node version | Copy `static/templates/.nvmrc` and `static/templates/.envrc`. See [direnv + nvm](/Standards/direnv) |
97
114
  | 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
115
  | 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
116
  | 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/` |
101
117
 
102
118
  The other standards are rules for how code is written. There is nothing to install for them: follow them in every change.
103
119
 
104
120
  **Finish by:**
105
121
 
106
- 1. Setting `**Code standards version:**` in `AGENTS.md` to the installed package's major version.
122
+ 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
123
  2. Running `pnpm lint`, `pnpm format:check` and the tests.
108
124
  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
125
 
@@ -124,7 +140,26 @@ The project already follows the standards, and a newer version is out.
124
140
 
125
141
  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
142
  4. **Skip any change to a standard the project opted out of.** The opt-outs are listed in `docs/development/coding-standards.md`.
127
- 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.
143
+ 5. **Do every other change** as its "What to do" says, and run its "How to check" search.
144
+ 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
145
 
130
146
  See the [Version History](/version-history) for the full update rules.
147
+
148
+ ---
149
+
150
+ ## Finishing a change later
151
+
152
+ 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 finished later, but **the version number must stay honest**.
153
+
154
+ 1. Set the project's version to the new version anyway.
155
+ 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, if the project tracks that.
156
+
157
+ ```md
158
+ ## Unfinished changes
159
+
160
+ - Version 2, change 4: the standard ESLint config is not switched on yet. Being done in ACT-120.
161
+ ```
162
+
163
+ 3. When it is finished, remove it from the list.
164
+
165
+ 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