@activatus/code-standards 3.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.
- package/README.md +1 -2
- package/docs/Guides/migrating.md +20 -12
- package/docs/Guides/setup.md +16 -9
- package/docs/Standards/human-readable-names.md +2 -2
- package/docs/Standards/lint-errors.md +3 -39
- package/docs/Standards/tech-stack.md +0 -1
- package/docs/Structure/folder-structure.md +1 -1
- package/docs/templates.mdx +0 -14
- package/docs/version-history.md +21 -15
- package/package.json +1 -1
- package/scripts/renameSymbol.mjs +49 -7
- package/static/templates/AGENTS.md +1 -1
- package/static/templates/husky/pre-commit +0 -1
package/README.md
CHANGED
|
@@ -144,8 +144,7 @@ static/templates/
|
|
|
144
144
|
├── prettier.config.mjs # ✨ Formatting
|
|
145
145
|
├── globals.css # 🎨 Tailwind + starter colour palette
|
|
146
146
|
├── .editorconfig # ⌨️ Editor whitespace rules
|
|
147
|
-
|
|
148
|
-
└── husky/pre-commit # 🚦 Lint before every commit
|
|
147
|
+
└── .nvmrc / .envrc # 🟢 Node version switching
|
|
149
148
|
```
|
|
150
149
|
|
|
151
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.
|
package/docs/Guides/migrating.md
CHANGED
|
@@ -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
|
|
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,7 +19,7 @@ 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
|
|
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
|
|
@@ -33,7 +33,7 @@ Format everything at once:
|
|
|
33
33
|
pnpm prettier --write .
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
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
|
|
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
|
|
|
@@ -101,9 +101,9 @@ These come up in nearly every project:
|
|
|
101
101
|
|
|
102
102
|
`docs/`, `docsSite/`, `DOCS_URL` and `pnpm docs:dev` already follow the standard. Leave them.
|
|
103
103
|
|
|
104
|
-
### 3. Rename in this order
|
|
104
|
+
### 3. Rename in this order
|
|
105
105
|
|
|
106
|
-
1. **Folders**, with `git mv` so the history follows the files. Fix the imports
|
|
106
|
+
1. **Folders**, with `git mv` so the history follows the files. Fix the imports at the same time.
|
|
107
107
|
2. **Types**, so the `@typescript-eslint/naming-convention` errors clear.
|
|
108
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.
|
|
109
109
|
4. **Everything the linter can't see** — form fields, union values, routes, scripts, environment variables. Search for each one by hand.
|
|
@@ -117,7 +117,7 @@ Some names are used outside the code. Renaming them needs more than a code chang
|
|
|
117
117
|
- **API routes and request fields** used by another app need both names to work until that app is updated.
|
|
118
118
|
- **Routes people have bookmarked** need a redirect from the old path.
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
Tell the person about each of these, so nobody gets caught out.
|
|
121
121
|
|
|
122
122
|
### Renaming from the command line
|
|
123
123
|
|
|
@@ -132,6 +132,18 @@ node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <cur
|
|
|
132
132
|
node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs components/ui/button/types.ts ButtonProperties ButtonProps
|
|
133
133
|
```
|
|
134
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
|
+
|
|
135
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.
|
|
136
148
|
- **Shorthand stays correct.** `{ properties }` becomes `{ properties: props }`, so objects keep their shape.
|
|
137
149
|
- **It only renames TypeScript and JavaScript names.** Folders, files, form fields, routes and environment variables still need renaming by hand.
|
|
@@ -150,12 +162,8 @@ Copy the eight [standard skill files](/templates#skills) into `.agents/skills/`,
|
|
|
150
162
|
|
|
151
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`.
|
|
152
164
|
|
|
153
|
-
## Stage 8 — Lint before every commit
|
|
154
|
-
|
|
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).
|
|
156
|
-
|
|
157
165
|
## Tips
|
|
158
166
|
|
|
159
|
-
- **Don't mix formatting and logic changes
|
|
167
|
+
- **Don't mix formatting and logic changes.** Reformat on its own, then change the code.
|
|
160
168
|
- **Exclude generated files** from ESLint with `// eslint-disable-file` or `.eslintignore`-equivalent glob ignores in the config.
|
|
161
169
|
- **Fix new-file compliance first**: agree that all _new_ files must pass the full ruleset even before the migration is complete.
|
package/docs/Guides/setup.md
CHANGED
|
@@ -70,13 +70,21 @@ Tell me the numbers to skip or change, or say "all good".
|
|
|
70
70
|
16. Imports: no circular imports, import from folders not files
|
|
71
71
|
17. API routes: one folder per route, kebab-case
|
|
72
72
|
18. Docs: every file in docs/ is a Decision Doc, shown at /docs by the docs site
|
|
73
|
-
19.
|
|
74
|
-
20.
|
|
75
|
-
21.
|
|
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
|
|
75
|
+
21. AGENTS.md and the eight agent skills
|
|
76
|
+
22. Removed in version 3: whether agents commit is the project's own workflow
|
|
77
|
+
23. The Ontology: the shared words for code
|
|
76
78
|
```
|
|
77
79
|
|
|
78
80
|
Then wait for the answer.
|
|
79
81
|
|
|
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
|
+
|
|
80
88
|
| The person says | Do |
|
|
81
89
|
| --------------------------------------- | ----------------------------- |
|
|
82
90
|
| "All good" | Apply every standard |
|
|
@@ -94,7 +102,7 @@ Do only the standards the person agreed to. Copy every file from `node_modules/@
|
|
|
94
102
|
|
|
95
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.
|
|
96
104
|
|
|
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
|
|
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.
|
|
98
106
|
|
|
99
107
|
| Standard | What to set up |
|
|
100
108
|
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -105,8 +113,7 @@ Do only the standards the person agreed to. Copy every file from `node_modules/@
|
|
|
105
113
|
| 10. Node version | Copy `static/templates/.nvmrc` and `static/templates/.envrc`. See [direnv + nvm](/Standards/direnv) |
|
|
106
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 |
|
|
107
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) |
|
|
108
|
-
|
|
|
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/` |
|
|
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/` |
|
|
110
117
|
|
|
111
118
|
The other standards are rules for how code is written. There is nothing to install for them: follow them in every change.
|
|
112
119
|
|
|
@@ -133,7 +140,7 @@ The project already follows the standards, and a newer version is out.
|
|
|
133
140
|
|
|
134
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.
|
|
135
142
|
4. **Skip any change to a standard the project opted out of.** The opt-outs are listed in `docs/development/coding-standards.md`.
|
|
136
|
-
5. **Do every other change** as its "What to do" says, and run its "How to check" search.
|
|
143
|
+
5. **Do every other change** as its "What to do" says, and run its "How to check" search.
|
|
137
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).
|
|
138
145
|
|
|
139
146
|
See the [Version History](/version-history) for the full update rules.
|
|
@@ -142,10 +149,10 @@ See the [Version History](/version-history) for the full update rules.
|
|
|
142
149
|
|
|
143
150
|
## Finishing a change later
|
|
144
151
|
|
|
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
|
|
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**.
|
|
146
153
|
|
|
147
154
|
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
|
|
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.
|
|
149
156
|
|
|
150
157
|
```md
|
|
151
158
|
## Unfinished changes
|
|
@@ -131,7 +131,7 @@ Some short names are not abbreviations. They are the word people actually say, a
|
|
|
131
131
|
| `docs` | A project's documentation | `docs/`, `docsSite/`, `DOCS_URL`, `pnpm docs:dev` |
|
|
132
132
|
| `lib` | The folder for outside connections and app-wide setup. Next.js and shadcn/ui use the same name | `lib/`, `lib/integrations/` |
|
|
133
133
|
| `props` | The values a component takes | `props`, `ButtonProps` |
|
|
134
|
-
| `ref` | A
|
|
134
|
+
| `ref` | A reference or handle to something: a React ref, or any other handle, such as a terminal tab's ref | `inputRef`, `useRef`, `surfaceRef` |
|
|
135
135
|
| `repo` | A repository: in GitHub's words, it "contains all of your project's files and each file's revision history" | `repoName`, `repoUrl` |
|
|
136
136
|
| `utils` | Reusable functions that are not components | `utils/`, `utils/formatCurrency/` |
|
|
137
137
|
| `app` | The application | `app/`, `appName` |
|
|
@@ -150,7 +150,7 @@ Some short names are not abbreviations. They are the word people actually say, a
|
|
|
150
150
|
When a short name feels like a dictionary word, don't just use it — add it here first:
|
|
151
151
|
|
|
152
152
|
1. **Ask:** is this the word people actually say, so the long form would only be harder to read? `docs`, `repo`: yes. `env`, `btn`, `msg`: no.
|
|
153
|
-
2. **Add a row** to the table above,
|
|
153
|
+
2. **Add a row** to the table above, before or alongside the code that uses it.
|
|
154
154
|
3. **If ESLint flags the word**, add it to `replacements` in the `unicorn/name-replacements` rule of the [ESLint config](/Standards/eslint), so the linter agrees: `replacements: { docs: false, lib: false, props: false, ref: false, repo: false, utils: false }`.
|
|
155
155
|
|
|
156
156
|
The list is the record. If a word is not on it, it is not a dictionary word yet.
|
|
@@ -128,44 +128,8 @@ Nothing else is switched off. If another rule seems impossible to satisfy, the c
|
|
|
128
128
|
|
|
129
129
|
---
|
|
130
130
|
|
|
131
|
-
##
|
|
131
|
+
## When lint must pass
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
**Work is not finished until `pnpm lint` passes.** That goes for people and AI agents alike: an agent fixes every lint error before it says a task is done.
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
| --------------------------------------------------------------- | ------------------------- | ------------------------------------------------------------------------ |
|
|
137
|
-
| **AI agents** | Before finishing any task | The agent fixes the error. Its work is not done until `pnpm lint` passes |
|
|
138
|
-
| **Git hook** ([`.husky/pre-commit`](#lint-before-every-commit)) | On every commit | The commit is refused until the errors are fixed |
|
|
139
|
-
| **CI** | On every change pushed | The change cannot be merged |
|
|
140
|
-
|
|
141
|
-
## Lint before every commit
|
|
142
|
-
|
|
143
|
-
A [Husky](https://typicode.github.io/husky/) git hook runs `pnpm lint` before every commit, so code that breaks the standards cannot be committed.
|
|
144
|
-
|
|
145
|
-
1. Install Husky:
|
|
146
|
-
|
|
147
|
-
```bash
|
|
148
|
-
pnpm add -D husky
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
2. Add the `prepare` script to `package.json`, so the hook is installed whenever someone runs `pnpm install`:
|
|
152
|
-
|
|
153
|
-
```json
|
|
154
|
-
{
|
|
155
|
-
"scripts": {
|
|
156
|
-
"prepare": "husky"
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
3. Copy the hook file [`.husky/pre-commit`](/templates#husky-pre-commit):
|
|
162
|
-
|
|
163
|
-
```text title=".husky/pre-commit"
|
|
164
|
-
pnpm lint
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
4. Run `pnpm install` once to switch it on.
|
|
168
|
-
|
|
169
|
-
**Add the hook last**, once the project already passes `pnpm lint`. Otherwise every commit is refused until the whole codebase is fixed.
|
|
170
|
-
|
|
171
|
-
How the project names commits and branches, and who may commit, is up to the project. See [Project workflow](/Standards/agent-specs#project-workflow).
|
|
135
|
+
How a project makes sure of it, such as a git hook or a check that runs on every change, is the project's own choice. See [Project workflow](/Standards/agent-specs#project-workflow).
|
|
@@ -189,7 +189,7 @@ Three folders hold functions that are not components. Each function belongs in e
|
|
|
189
189
|
- **Pages, API routes and server actions stay thin.** They take the request, call a function in `services/`, and return the result. Business logic never lives in them.
|
|
190
190
|
- **`services/` uses `lib/` to reach the outside world.** A service that charges a card calls the Stripe client in `lib/integrations/stripe/`, never the Stripe package directly.
|
|
191
191
|
- **`utils/` uses nothing outside itself.** If a function needs a database, an API or the environment, it is not a util: it belongs in `services/` or `lib/`.
|
|
192
|
-
- **Group `services/` by the
|
|
192
|
+
- **Group `services/` by the project's own ontology word it works on**, one folder per function: `services/invoice/createInvoice/`. The project's ontology is usually in `docs/product/ontology.md`, but it can be in another file. If you can't find it, ask.
|
|
193
193
|
|
|
194
194
|
## 🧰 Utils
|
|
195
195
|
|
package/docs/templates.mdx
CHANGED
|
@@ -33,7 +33,6 @@ import docsSiteGitignore from "!!raw-loader!@site/static/templates/docsSite/giti
|
|
|
33
33
|
import decisionDoc from "!!raw-loader!@site/static/templates/decision-doc.md";
|
|
34
34
|
import docsSiteHome from "!!raw-loader!@site/static/templates/docsSite/src/pages/index.tsx";
|
|
35
35
|
import nextConfig from "!!raw-loader!@site/static/templates/next.config.mjs";
|
|
36
|
-
import huskyPreCommit from "!!raw-loader!@site/static/templates/husky/pre-commit";
|
|
37
36
|
|
|
38
37
|
# Templates
|
|
39
38
|
|
|
@@ -58,7 +57,6 @@ Each file is also served as a plain file, so a person or an AI agent can fetch i
|
|
|
58
57
|
| [Node version](#nvmrc) | `.nvmrc` in the project root | [`/templates/.nvmrc`](pathname:///templates/.nvmrc) |
|
|
59
58
|
| [direnv](#envrc) | `.envrc` in the project root | [`/templates/.envrc`](pathname:///templates/.envrc) |
|
|
60
59
|
| [Agent skills](#skills) | `.agents/skills/` and `.claude/commands/` | Eight files — see [below](#skills) |
|
|
61
|
-
| [Lint before commit](#husky-pre-commit) | `.husky/pre-commit` | [`/templates/husky/pre-commit`](pathname:///templates/husky/pre-commit) |
|
|
62
60
|
| [Docs site](#docs-site) | `docsSite/` in the project root | Several files — see [below](#docs-site) |
|
|
63
61
|
| [`/docs` route](#docs-route) | `next.config.mjs` | [`/templates/next.config.mjs`](pathname:///templates/next.config.mjs) |
|
|
64
62
|
| [Document templates](#document-templates) | `docs/` in the project root | Several files — see [below](#document-templates) |
|
|
@@ -292,18 +290,6 @@ Runs the test suite; reports failures grouped by cause, tests that never ran, an
|
|
|
292
290
|
|
|
293
291
|
---
|
|
294
292
|
|
|
295
|
-
## Lint before commit {#husky-pre-commit}
|
|
296
|
-
|
|
297
|
-
**Copy to:** `.husky/pre-commit` in the project root
|
|
298
|
-
|
|
299
|
-
Refuses a commit while `pnpm lint` reports errors. See [Lint before every commit](/Standards/lint-errors#lint-before-every-commit). Plain file: [`/templates/husky/pre-commit`](pathname:///templates/husky/pre-commit)
|
|
300
|
-
|
|
301
|
-
<CodeBlock language="text" title=".husky/pre-commit">
|
|
302
|
-
{huskyPreCommit}
|
|
303
|
-
</CodeBlock>
|
|
304
|
-
|
|
305
|
-
---
|
|
306
|
-
|
|
307
293
|
## Docs site {#docs-site}
|
|
308
294
|
|
|
309
295
|
**Copy to:** a `docsSite/` folder in the project root
|
package/docs/version-history.md
CHANGED
|
@@ -21,30 +21,37 @@ sidebar_label: "Version History"
|
|
|
21
21
|
2. **Update the package:** `pnpm update @activatus/code-standards --latest`. Then read this page from `node_modules/@activatus/code-standards/docs/version-history.md`.
|
|
22
22
|
3. **Read each version newer than the project's**, oldest first. Skip any change to a standard the project opted out of: they are listed in `docs/development/coding-standards.md`.
|
|
23
23
|
4. **For each change, do the "What to do" steps**, then run the "How to check" searches. A search that still finds something means the change is not finished.
|
|
24
|
-
5. **
|
|
25
|
-
6. **
|
|
26
|
-
7. **Update the version number** in `AGENTS.md` once every change is done.
|
|
24
|
+
5. **Run `pnpm lint`, `pnpm test` and the build** after each change.
|
|
25
|
+
6. **Update the version number** in `AGENTS.md` once every change is done.
|
|
27
26
|
|
|
28
27
|
**When a change does not fit the project**, for example it renames a folder the project does not have, skip it. If you are not sure, ask; do not guess.
|
|
29
28
|
|
|
30
29
|
## Adding a version
|
|
31
30
|
|
|
32
|
-
Anyone changing the standards adds a version,
|
|
31
|
+
Anyone changing the standards adds a version, alongside the change:
|
|
33
32
|
|
|
34
33
|
- **One version per release**, numbered one higher than the last. Whole numbers only. A version can collect several changes before it is released.
|
|
35
34
|
- **Bump the package's major version to match** in `package.json`: version 3 is `3.0.0`. Then publish it to npm (npmjs.com) with `pnpm publish`. pnpm is the tool; npm is where the package lives, and projects install it from there with `pnpm add`.
|
|
36
35
|
- **For every change, write:** what changed, why, what to do in a project, and how to check it is done. Write it for an agent that has not read the rest of the standards.
|
|
37
36
|
- **If a project has nothing to do, say so.**
|
|
38
37
|
- **Newest version at the top.**
|
|
39
|
-
- **Work in progress goes under `## Version N — not released yet`**, with a line saying projects should not apply it yet. Changes can be added to it over
|
|
38
|
+
- **Work in progress goes under `## Version N — not released yet`**, with a line saying projects should not apply it yet. Changes can be added to it over time. To release it: drop "not released yet", add the **Released** date and **Updates from** line, set `package.json` to `N.0.0`, then publish.
|
|
39
|
+
- **Fixing a released version** bumps only the last number: `3.0.0` → `3.0.1`. Update the version's changes in place, and list what was fixed under its **Fixes**. Projects keep the same version number in `AGENTS.md`.
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
43
43
|
## Version 3
|
|
44
44
|
|
|
45
|
-
**Released:** 2026-10-17 · **Updates from:** version 2
|
|
45
|
+
**Released:** 2026-10-17 · **Updates from:** version 2 · **Latest fix:** 3.0.1
|
|
46
46
|
|
|
47
|
-
Install it with `pnpm add -D @activatus/code-standards@3.0.
|
|
47
|
+
Install it with `pnpm add -D @activatus/code-standards@3.0.1`. Do change 1 first: it says which parts of the project's `AGENTS.md` are now the project's own to write.
|
|
48
|
+
|
|
49
|
+
**Fixes in 3.0.1.** If the project already applied 3.0.0, check these:
|
|
50
|
+
|
|
51
|
+
- Setup list numbers are permanent again: 19, 20 and 22 are marked removed, and AGENTS.md and the Ontology are back to 21 and 23. Choices recorded under the version 2 numbers are still right.
|
|
52
|
+
- The Husky lint hook is no longer a standard. Lint must pass before work is finished; how that is enforced is the project's choice.
|
|
53
|
+
- Every name ending in `Reference` uses `Ref`, not only React refs.
|
|
54
|
+
- The rename script takes a list of renames with `--list`.
|
|
48
55
|
|
|
49
56
|
### 1. Project workflow is no longer part of the standards
|
|
50
57
|
|
|
@@ -53,10 +60,10 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.0`. Do change 1 first
|
|
|
53
60
|
**What to do:**
|
|
54
61
|
|
|
55
62
|
- The Branch Naming and Commit Messages standards are gone, along with standards 19, 20 and 22 from the setup list. Keep whatever the project already does, and make sure it is written up in the project's own docs, usually `docs/development/`.
|
|
56
|
-
-
|
|
63
|
+
- **Standards 19, 20 and 22 keep their numbers, marked as removed.** No other number changes. If `docs/development/coding-standards.md` records a choice for 19, 20 or 22, move that rule into Project workflow and take it off the list.
|
|
64
|
+
- In `AGENTS.md`, replace the "Development workflow" section with a **Project workflow** section, copied from the [template](/templates#agents). Fill it in with the project's own rules: who commits, branches, commit messages, Pull Requests, merging and releases. Put the most important rule for agents, usually whether they may commit, at the very top: one line, or a short section if it needs more.
|
|
57
65
|
- Remove the "Never commit code" and "Do not create, switch or delete branches" lines from "Out of scope for AI agents", unless they are the project's own rule. If they are, they belong in Project workflow.
|
|
58
|
-
- Commitlint and the `.husky/commit-msg`
|
|
59
|
-
- **Keep `.husky/pre-commit`.** Running `pnpm lint` before every commit is still a standard. See [Lint before every commit](/Standards/lint-errors#lint-before-every-commit).
|
|
66
|
+
- Commitlint and the Husky hooks (`.husky/commit-msg` and `.husky/pre-commit`) are no longer templates. Keep them if the project wants them: they are now the project's choice. The standard is only that `pnpm lint` passes before work is finished. See [When lint must pass](/Standards/lint-errors#when-lint-must-pass).
|
|
60
67
|
|
|
61
68
|
**How to check:** `AGENTS.md` has a Project workflow section, and every rule in it is written up in the project's docs.
|
|
62
69
|
|
|
@@ -67,7 +74,7 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.0`. Do change 1 first
|
|
|
67
74
|
**What to do:**
|
|
68
75
|
|
|
69
76
|
- Rename the `library/` folder to `lib/` with `git mv`, and fix the imports: `@/library/` → `@/lib/`.
|
|
70
|
-
- Rename
|
|
77
|
+
- Rename every name ending in `Reference` to end in `Ref`, whatever it refers to: `inputReference` → `inputRef`, `surfaceReference` → `surfaceRef`. Rename `repository` back to `repo` where it is short for a Git repository, such as `repositoryName` → `repoName`. Use the editor's Rename Symbol (F2), or the [rename script](/Guides/migrating#renaming-from-the-command-line).
|
|
71
78
|
- Copy the new [ESLint config](/Standards/eslint). The naming rule now has `replacements: { docs: false, lib: false, props: false, ref: false, repo: false, utils: false }` and `allowList: { params: true, searchParams: true }`.
|
|
72
79
|
- Update the "Dictionary words stay short" line in `AGENTS.md` from the [template](/templates#agents), and remove `lib/` → `library/` and `repo` → `repository` from its Never / Always table.
|
|
73
80
|
|
|
@@ -108,7 +115,7 @@ Install it with `pnpm add -D @activatus/code-standards@3.0.0`. Do change 1 first
|
|
|
108
115
|
**What to do:**
|
|
109
116
|
|
|
110
117
|
- Copy the new [`prettier.config.mjs`](/templates#prettier) and [`.editorconfig`](/templates#editorconfig). Prettier now has `printWidth: 70` and `useTabs: true`, and keeps spaces for Markdown and YAML. EditorConfig indents with tabs, except Markdown, YAML and Python.
|
|
111
|
-
- Run `pnpm format` once, on its own,
|
|
118
|
+
- Run `pnpm format` once, on its own, with no other changes mixed in. It touches nearly every file, so keep it apart from real changes.
|
|
112
119
|
- If the project shows code on a web page, such as its docs site, add `pre, code { tab-size: 2; }` to its CSS, so tabs are not shown 8 characters wide. The [`docsSite/` template](/templates#docs-site) already has it.
|
|
113
120
|
|
|
114
121
|
**How to check:** `pnpm format:check` passes.
|
|
@@ -145,7 +152,7 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
145
152
|
|
|
146
153
|
### 10. Unfinished changes are recorded, not hidden
|
|
147
154
|
|
|
148
|
-
**Why:** A big change, such as switching on the standard ESLint config, may be
|
|
155
|
+
**Why:** A big change, such as switching on the standard ESLint config, may be finished later. The version number has to stay honest about that.
|
|
149
156
|
|
|
150
157
|
**What to do:** Add an "Unfinished changes" section to `docs/development/coding-standards.md`, from the [template](/templates#document-templates). List any change from any version that is not done yet, with what is left and where it is being done, or write "None". See [Finishing a change later](/Guides/setup#finishing-a-change-later).
|
|
151
158
|
|
|
@@ -154,11 +161,10 @@ See [When a name clashes](/Standards/human-readable-names#when-a-name-clashes).
|
|
|
154
161
|
### No action needed
|
|
155
162
|
|
|
156
163
|
- The [Ontology](/ontology) defines `dependency`: something the code relies on but does not define itself. Ticket relationships are not dependencies; each project names those itself.
|
|
157
|
-
- The package now ships a rename script for agents working from the command line, using TypeScript's own rename: `node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>`. See [Renaming from the command line](/Guides/migrating#renaming-from-the-command-line).
|
|
164
|
+
- The package now ships a rename script for agents working from the command line, using TypeScript's own rename: `node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>`. Pass `--list renames.txt` to do many renames in one run, one per line. It can't reach keys in untyped object literals, such as the expected value in a test's `toEqual({ … })`: search the tests for old names and fix those by hand. See [Renaming from the command line](/Guides/migrating#renaming-from-the-command-line).
|
|
158
165
|
- The [Setup](/Guides/setup) guide says the standards are a base for code only, and explains how to get past pnpm's `minimumReleaseAge` when a new version is too fresh to install.
|
|
159
166
|
- [Folder Structure](/Structure/folder-structure) explains each `lib/` folder in one line.
|
|
160
167
|
- The [ESLint page](/Standards/eslint#installation) says the config needs ESLint 10.4 or later, and the React configs explain why they set `settings.react.version`.
|
|
161
|
-
- "Lint before every commit" moved to [Lint Errors](/Standards/lint-errors#lint-before-every-commit).
|
|
162
168
|
|
|
163
169
|
---
|
|
164
170
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@activatus/code-standards",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "The Activatus code standards: the rules as Markdown, and the config files to copy. Install it so an AI agent can read the standards from node_modules.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
package/scripts/renameSymbol.mjs
CHANGED
|
@@ -6,14 +6,23 @@
|
|
|
6
6
|
// node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs <file> <currentName> <newName>
|
|
7
7
|
// For example:
|
|
8
8
|
// node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs components/ui/button/types.ts ButtonProperties ButtonProps
|
|
9
|
+
//
|
|
10
|
+
// To do many renames in one run, list them in a text file, one per line: <file> <currentName> <newName>.
|
|
11
|
+
// Blank lines and lines starting with # are skipped. The renames run in order.
|
|
12
|
+
// node node_modules/@activatus/code-standards/scripts/renameSymbol.mjs --list renames.txt
|
|
9
13
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
10
14
|
import { createRequire } from "node:module";
|
|
11
15
|
import path from "node:path";
|
|
12
16
|
|
|
13
17
|
// process.argv starts with the node binary and this script's path.
|
|
14
18
|
const FIRST_ARGUMENT_INDEX = 2;
|
|
15
|
-
const
|
|
16
|
-
|
|
19
|
+
const LIST_FLAG = "--list";
|
|
20
|
+
// A rename line has three parts: file, current name, new name.
|
|
21
|
+
const RENAME_PARTS = 3;
|
|
22
|
+
const USAGE = [
|
|
23
|
+
"Usage: node renameSymbol.mjs <file> <currentName> <newName>",
|
|
24
|
+
" or: node renameSymbol.mjs --list <file of renames>",
|
|
25
|
+
].join("\n");
|
|
17
26
|
|
|
18
27
|
// Uses the project's own TypeScript, so the rename matches the project's compiler exactly.
|
|
19
28
|
const requireFromProject = createRequire(
|
|
@@ -176,12 +185,45 @@ const renameSymbol = ({ filePath, currentName, newName }) => {
|
|
|
176
185
|
return `Renamed ${currentName} to ${newName}: ${renameLocations.length} places in ${fileCount} ${fileWord}.`;
|
|
177
186
|
};
|
|
178
187
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
)
|
|
188
|
+
// Each line of a list file is one rename: <file> <currentName> <newName>.
|
|
189
|
+
const readRenameList = (listPath) =>
|
|
190
|
+
readFileSync(listPath, "utf8")
|
|
191
|
+
.split("\n")
|
|
192
|
+
.map((line) => line.trim())
|
|
193
|
+
.filter((line) => line !== "" && !line.startsWith("#"))
|
|
194
|
+
.map((line) => {
|
|
195
|
+
const [filePath, currentName, newName] = line.split(
|
|
196
|
+
/\s+/u,
|
|
197
|
+
RENAME_PARTS,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
return { filePath, currentName, newName };
|
|
201
|
+
});
|
|
182
202
|
|
|
183
|
-
|
|
184
|
-
|
|
203
|
+
const isCompleteRename = ({ filePath, currentName, newName }) =>
|
|
204
|
+
Boolean(filePath && currentName && newName);
|
|
205
|
+
|
|
206
|
+
const commandArguments = process.argv.slice(FIRST_ARGUMENT_INDEX);
|
|
207
|
+
const [firstArgument, secondArgument] = commandArguments;
|
|
208
|
+
const renames =
|
|
209
|
+
firstArgument === LIST_FLAG && secondArgument
|
|
210
|
+
? readRenameList(secondArgument)
|
|
211
|
+
: [
|
|
212
|
+
{
|
|
213
|
+
filePath: commandArguments[0],
|
|
214
|
+
currentName: commandArguments[1],
|
|
215
|
+
newName: commandArguments[2],
|
|
216
|
+
},
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
if (
|
|
220
|
+
renames.length > 0 &&
|
|
221
|
+
renames.every((rename) => isCompleteRename(rename))
|
|
222
|
+
) {
|
|
223
|
+
// Each rename reloads the project, so it sees the renames before it.
|
|
224
|
+
for (const rename of renames) {
|
|
225
|
+
console.log(renameSymbol(rename));
|
|
226
|
+
}
|
|
185
227
|
} else {
|
|
186
228
|
console.error(USAGE);
|
|
187
229
|
process.exitCode = 1;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# [Project Name]
|
|
2
2
|
|
|
3
|
-
> [The project's most important
|
|
3
|
+
> [The project's most important rule for agents, stated first so every agent sees it. Usually whether an agent may commit, push or make branches. One line, or a short section if it needs more, such as which agents may commit, when, and how the others ask. See "Project workflow" below.]
|
|
4
4
|
|
|
5
5
|
> **"go" means carry on.** When the person sends only "go", carry on with the current task. It is never permission to commit, push or open a Pull Request, and it needs no reply asking what they meant.
|
|
6
6
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
pnpm lint
|