@next-friday/create-app 9.0.0 → 9.1.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 (57) hide show
  1. package/package.json +4 -2
  2. package/templates/base/.agents/review.md +1 -1
  3. package/templates/base/.agents/skills/sdlc/SKILL.md +14 -12
  4. package/templates/base/.agents/skills/sdlc/playbooks/build.md +10 -9
  5. package/templates/base/.agents/skills/sdlc/playbooks/deploy.md +9 -0
  6. package/templates/base/.agents/skills/sdlc/playbooks/design.md +8 -5
  7. package/templates/base/.agents/skills/sdlc/playbooks/maintain.md +21 -0
  8. package/templates/base/.agents/skills/sdlc/playbooks/open-pr.md +4 -4
  9. package/templates/base/.agents/skills/sdlc/playbooks/plan.md +5 -5
  10. package/templates/base/.agents/skills/sdlc/playbooks/review.md +12 -5
  11. package/templates/base/.agents/skills/sdlc-help/SKILL.md +4 -5
  12. package/templates/base/.claude/skills/sdlc/SKILL.md +14 -12
  13. package/templates/base/.claude/skills/sdlc/playbooks/build.md +10 -9
  14. package/templates/base/.claude/skills/sdlc/playbooks/deploy.md +9 -0
  15. package/templates/base/.claude/skills/sdlc/playbooks/design.md +8 -5
  16. package/templates/base/.claude/skills/sdlc/playbooks/maintain.md +21 -0
  17. package/templates/base/.claude/skills/sdlc/playbooks/open-pr.md +4 -4
  18. package/templates/base/.claude/skills/sdlc/playbooks/plan.md +5 -5
  19. package/templates/base/.claude/skills/sdlc/playbooks/review.md +12 -5
  20. package/templates/base/.claude/skills/sdlc-help/SKILL.md +4 -5
  21. package/templates/base/.cursor/skills/sdlc/SKILL.md +14 -12
  22. package/templates/base/.cursor/skills/sdlc/playbooks/build.md +10 -9
  23. package/templates/base/.cursor/skills/sdlc/playbooks/deploy.md +9 -0
  24. package/templates/base/.cursor/skills/sdlc/playbooks/design.md +8 -5
  25. package/templates/base/.cursor/skills/sdlc/playbooks/maintain.md +21 -0
  26. package/templates/base/.cursor/skills/sdlc/playbooks/open-pr.md +4 -4
  27. package/templates/base/.cursor/skills/sdlc/playbooks/plan.md +5 -5
  28. package/templates/base/.cursor/skills/sdlc/playbooks/review.md +12 -5
  29. package/templates/base/.cursor/skills/sdlc-help/SKILL.md +4 -5
  30. package/templates/base/.github/ISSUE_TEMPLATE/documentation.yml +25 -0
  31. package/templates/base/REVIEW.md +1 -1
  32. package/templates/base/SECURITY.md +1 -1
  33. package/templates/base/SETUP.md +9 -13
  34. package/templates/base/bands.yaml +2 -3
  35. package/templates/base/intent/README.md +2 -4
  36. package/templates/base/lessons/README.md +5 -0
  37. package/templates/base/scripts/check-intent.ts +391 -0
  38. package/templates/nestjs/.github/workflows/ci.yml +2 -0
  39. package/templates/nestjs/AGENTS.md +9 -17
  40. package/templates/nestjs/CONTRIBUTING.md +1 -0
  41. package/templates/nestjs/package.json +2 -1
  42. package/templates/nextjs/.github/workflows/ci.yml +2 -0
  43. package/templates/nextjs/AGENTS.md +9 -17
  44. package/templates/nextjs/CONTRIBUTING.md +1 -0
  45. package/templates/nextjs/package.json +2 -1
  46. package/templates/nodejs/.github/workflows/ci.yml +2 -0
  47. package/templates/nodejs/AGENTS.md +8 -16
  48. package/templates/nodejs/CONTRIBUTING.md +1 -0
  49. package/templates/nodejs/package.json +2 -1
  50. package/templates/payload/.github/workflows/ci.yml +2 -0
  51. package/templates/payload/AGENTS.md +10 -18
  52. package/templates/payload/CONTRIBUTING.md +1 -0
  53. package/templates/payload/package.json +2 -1
  54. package/templates/turborepo/.github/workflows/ci.yml +2 -0
  55. package/templates/turborepo/AGENTS.md +10 -18
  56. package/templates/turborepo/CONTRIBUTING.md +1 -0
  57. package/templates/turborepo/package.json +2 -1
@@ -20,7 +20,6 @@ TypeScript HTTP service on `node:http`, without a framework, on pnpm and Node.js
20
20
  - Lint: `pnpm verify:static` (ESLint allows zero warnings; prints `✔ no dependency violations found`)
21
21
 
22
22
  Run all three before reporting any task complete, and paste the output. `pnpm verify` runs all three.
23
- If a test fails, fix the code, not the test.
24
23
 
25
24
  ## Architecture
26
25
 
@@ -29,23 +28,16 @@ If a test fails, fix the code, not the test.
29
28
 
30
29
  ## Conventions
31
30
 
32
- 1. **Follow `.agents/rules/`.** `.agents/rules.json` gives each rule's scope; Claude Code and Cursor load them. After changing either, or a skill or subagent in `.agents/skills/` or `.agents/agents/`, run `pnpm rules:sync`; `pnpm check` fails on stale copies.
33
- 2. **Put tests next to the code as `src/**/*.test.ts`.** Vitest collects only that pattern.
34
- 3. **Read configuration from environment variables and fail when one is missing**, as `parsePort` does. Document each variable in `.env.example`; `pnpm start` and `pnpm start:dev` load `.env`.
35
- 4. **Start from the accepted spec, in plan mode.** Claude Code starts every session in plan mode (`.claude/settings.json`); in Cursor, switch to Plan Mode before the first edit. Give the plan the change's `intent/<change>/intent.md` and `spec.md`, and have it name the files that change, the order of the work, and the tests that prove it. Commit the approved plan as `intent/<change>/plan.md`. When implementation departs from the plan, update `plan.md` in the same commit.
36
- 5. **Start a bug fix with a failing test.** Reproduce the bug as a test, run it, and confirm it fails for the reason you expect. Commit that test. Then create `.git/bug-fix-in-progress`, so `.agents/hooks/agent-test-edit-gate.sh` blocks test edits, and make the test pass without editing it. Delete `.git/bug-fix-in-progress` when the fix is done.
37
- 6. **Start work only when a person asks or a trigger runs it, and stop only at the human gates, before an irreversible action, or for a decision only a person can make.** A question or a statement gets an answer, not a file, a commit, or a pull request. When a message reports a problem without asking for work, answer in a few lines and end with the message that would start the work: `/sdlc` followed by their own words. Once a task starts, carry it to the next gate without asking; `.agents/rules/agent-owned-work.md` lists the gates.
38
- 7. **Branch from the latest `origin/main`, and open the pull request ready for review.** Name the branch `<type>/<short-description>` and fill the body from `.github/pull_request_template.md`. `.github/workflows/ci.yml` runs full verification only on a pull request that is not a draft. Drive it until it is green and waits only on code owner approval, as `.agents/skills/sdlc/playbooks/review.md` describes. Rebase and `git push --force-with-lease` only branches you own. Never merge a pull request: a person merges it with `--squash` after code owner approval, bottom-up for a stack of pull requests.
39
- 8. **Write replies a person can check.** Reply in the language the person wrote in. Write paths from the project root, such as `README.md:12`, never from the machine's root. State as a fact only what you opened or ran in this turn, and say what you ran; mark anything else as inferred or not checked. Answer what was asked and stop: leave out tools, services, and steps the request does not need, and never hand the person a check you could run. Send nothing outside the session, such as a message to another session or a service, unless a task step says to.
31
+ 1. **Put tests next to the code as `src/**/*.test.ts`.** Vitest collects only that pattern.
32
+ 2. **Read configuration from environment variables and fail when one is missing**, as `parsePort` does. Document each variable in `.env.example`; `pnpm start` and `pnpm start:dev` load `.env`.
33
+ 3. **Start from the accepted spec, in plan mode** (Cursor: Plan Mode). Give the plan the change's `intent/<change>/intent.md` and `spec.md`. Commit the approved plan as `intent/<change>/plan.md` with an `Accepted by:` line naming the engineer, as `.agents/skills/sdlc/playbooks/build.md` describes.
34
+ 4. **Start a bug fix with a failing test.** Reproduce the bug as a test, confirm it fails for the reason you expect, and commit it. Then create `.git/bug-fix-in-progress`, so `.agents/hooks/agent-test-edit-gate.sh` blocks test edits, make the test pass without editing it, and delete `.git/bug-fix-in-progress`.
35
+ 5. **Do not start work a person did not ask for.** When a message reports a problem without asking for work, answer in a few lines and end with the message that would start it: `/sdlc` followed by their own words.
36
+ 6. **Branch from the latest `origin/main`, and open the pull request ready for review.** Name the branch `<type>/<short-description>` and fill the body from `.github/pull_request_template.md`. `.github/workflows/ci.yml` runs full verification only on a pull request that is not a draft. Never merge a pull request: a person merges it with `--squash` after code owner approval, bottom-up for a stack of pull requests.
37
+ 7. **Write replies a person can check.** Reply in the language the person wrote in. Write paths from the project root, such as `README.md:12`, never from the machine's root. State as a fact only what you opened or ran in this turn, and say what you ran; mark anything else as inferred or not checked. Answer what was asked and stop: leave out tools, services, and steps the request does not need, and never hand the person a check you could run. Send nothing outside the session, such as a message to another session or a service, unless a task step says to.
40
38
 
41
39
  ## Things Claude gets wrong
42
40
 
43
41
  When Claude makes a mistake twice, add the correction here.
44
42
 
45
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It also blocks merging or approving a pull request, approving a deployment, and gh aliases, and asks the person before an irreversible git command such as a force push or a hard reset. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
46
- - **Production gate**: `.agents/hooks/agent-production-gate.sh` blocks a shell command that deploys to `prod` (`gh workflow run` or a workflow dispatch with `environment=prod`), a Railway CLI command that names `prod` with `-e`, `--environment`, or `railway environment`, and a release tag push, unless a release manager started the session with `RELEASE_APPROVAL` set. Report what is ready to promote instead. When a gated command appears only inside a message, write the text to a file with your file-editing tool, not a shell heredoc, and pass it with `git commit -F <file>` or `gh pr create --body-file <file>`. The gate reads only shell commands, so an MCP tool or a Railway command without `-e` or `--environment` passes it. It is a convenience, not a security boundary: the `prod` environment's required reviewers and Railway credentials are the boundary.
47
-
48
- ## Related documentation
49
-
50
- - [README.md](README.md): scripts, container, deploy
51
- - [CONTRIBUTING.md](CONTRIBUTING.md): prerequisites, Git hooks, pull requests
43
+ - **Production gate**: `.agents/hooks/agent-production-gate.sh` blocks a shell command that deploys to `prod`, runs a Railway CLI command that names `prod`, or pushes a release tag, unless a release manager started the session with `RELEASE_APPROVAL` set. Report what is ready to promote instead. When a gated command appears only inside a message, write the text to a file with your file-editing tool, not a shell heredoc, and pass it with `git commit -F <file>` or `gh pr create --body-file <file>`. The gate reads only shell commands, so an MCP tool or a Railway command without `-e` or `--environment` passes it.
@@ -49,6 +49,7 @@ We use trunk-based development. `main` is the only long-lived branch, and every
49
49
  - Branch from `main` and merge back within a day or two. Do not create `develop` or release branches.
50
50
  - Merge unfinished work behind a feature flag or keep it unreachable instead of holding a long-lived branch.
51
51
  - Pull requests are squash-merged, so the pull request title becomes the commit on `main`.
52
+ - After a pull request that only reformats code merges, the next pull request lists its commit on `main` in `.git-blame-ignore-revs` at the repository root, creating the file the first time, with a `#` comment that names the change, as [GitHub Docs](https://docs.github.com/en/repositories/working-with-files/using-files/viewing-and-understanding-files) shows. GitHub then hides that commit in the blame view.
52
53
  - Write commit messages in the format that `@next-friday/commitlint-config-friday` defines. Pull request titles use `<type>(<scope>): <subject>`, which `.github/workflows/validate-pr-title.yml` checks.
53
54
  - Keep each pull request focused on one cohesive change.
54
55
  - Describe observable endpoint, request or response, or configuration effects.
@@ -19,6 +19,7 @@
19
19
  "format:check": "prettier --check --cache . && editorconfig-checker",
20
20
  "gates:check": "node scripts/check-agent-gates.ts",
21
21
  "human-gates:check": "node scripts/check-human-gates.ts",
22
+ "intent:check": "node scripts/check-intent.ts",
22
23
  "knip": "knip",
23
24
  "lint": "eslint . --fix --cache --max-warnings=0 --no-inline-config",
24
25
  "lint:check": "eslint . --cache --max-warnings=0 --no-inline-config",
@@ -38,7 +39,7 @@
38
39
  "test:watch": "vitest",
39
40
  "typecheck": "tsc --noEmit -p tsconfig.json",
40
41
  "verify": "pnpm verify:static && pnpm test:coverage && pnpm build",
41
- "verify:static": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm human-gates:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm peers:check && pnpm typecheck && pnpm knip && pnpm depcruise"
42
+ "verify:static": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm human-gates:check && pnpm intent:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm peers:check && pnpm typecheck && pnpm knip && pnpm depcruise"
42
43
  },
43
44
  "devDependencies": {
44
45
  "@commitlint/cli": "21.2.4",
@@ -98,6 +98,8 @@ jobs:
98
98
  run: pnpm gates:check
99
99
  - name: Check human gates
100
100
  run: pnpm human-gates:check
101
+ - name: Self-test the intent checker
102
+ run: pnpm intent:check
101
103
  - name: Check lint
102
104
  run: pnpm lint:check
103
105
  - name: Check formatting
@@ -23,7 +23,6 @@ Payload CMS on Next.js App Router and PostgreSQL, in TypeScript on pnpm and Node
23
23
  - Lint: `pnpm verify:static` (ESLint allows zero warnings; prints `✔ no dependency violations found`)
24
24
 
25
25
  Run all three before reporting any task complete, and paste the output. `pnpm verify` runs all three.
26
- If a test fails, fix the code, not the test.
27
26
 
28
27
  ## Architecture
29
28
 
@@ -32,29 +31,22 @@ If a test fails, fix the code, not the test.
32
31
 
33
32
  ## Conventions
34
33
 
35
- 1. **Follow `.agents/rules/`.** `.agents/rules.json` gives each rule's scope; Claude Code and Cursor load them. After changing either, or a skill or subagent in `.agents/skills/` or `.agents/agents/`, run `pnpm rules:sync`; `pnpm check` fails on stale copies.
36
- 2. **Change the schema only through collections, then regenerate and commit.** Payload generates `src/app/(payload)/`, `src/payload-types.ts`, and `src/migrations/`; run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>`. Do not edit those files by hand.
37
- 3. **Put unit tests next to the code as `src/**/*.test.{ts,tsx}` and Playwright end-to-end tests in `test/` as `*.e2e.test.ts`.** Vitest collects only the first pattern.
38
- 4. **Component tests need a DOM test environment, and Vitest runs in Node.js.** Add that environment with the first component test.
39
- 5. **Read configuration through `requireEnvironment` in `src/environment.ts`.** Document each variable in `.env.example`.
40
- 6. **Start from the accepted spec, in plan mode.** Claude Code starts every session in plan mode (`.claude/settings.json`); in Cursor, switch to Plan Mode before the first edit. Give the plan the change's `intent/<change>/intent.md` and `spec.md`, and have it name the files that change, the order of the work, and the tests that prove it. Commit the approved plan as `intent/<change>/plan.md`. When implementation departs from the plan, update `plan.md` in the same commit.
41
- 7. **Start a bug fix with a failing test.** Reproduce the bug as a test, run it, and confirm it fails for the reason you expect. Commit that test. Then create `.git/bug-fix-in-progress`, so `.agents/hooks/agent-test-edit-gate.sh` blocks test edits, and make the test pass without editing it. Delete `.git/bug-fix-in-progress` when the fix is done.
42
- 8. **Start work only when a person asks or a trigger runs it, and stop only at the human gates, before an irreversible action, or for a decision only a person can make.** A question or a statement gets an answer, not a file, a commit, or a pull request. When a message reports a problem without asking for work, answer in a few lines and end with the message that would start the work: `/sdlc` followed by their own words. Once a task starts, carry it to the next gate without asking; `.agents/rules/agent-owned-work.md` lists the gates.
43
- 9. **Branch from the latest `origin/main`, and open the pull request ready for review.** Name the branch `<type>/<short-description>` and fill the body from `.github/pull_request_template.md`. `.github/workflows/ci.yml` runs full verification only on a pull request that is not a draft. Drive it until it is green and waits only on code owner approval, as `.agents/skills/sdlc/playbooks/review.md` describes. Rebase and `git push --force-with-lease` only branches you own. Never merge a pull request: a person merges it with `--squash` after code owner approval, bottom-up for a stack of pull requests.
44
- 10. **Write replies a person can check.** Reply in the language the person wrote in. Write paths from the project root, such as `README.md:12`, never from the machine's root. State as a fact only what you opened or ran in this turn, and say what you ran; mark anything else as inferred or not checked. Answer what was asked and stop: leave out tools, services, and steps the request does not need, and never hand the person a check you could run. Send nothing outside the session, such as a message to another session or a service, unless a task step says to.
34
+ 1. **Change the schema only through collections, then regenerate and commit.** Payload generates `src/app/(payload)/`, `src/payload-types.ts`, and `src/migrations/`; run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>`. Do not edit those files by hand.
35
+ 2. **Put unit tests next to the code as `src/**/*.test.{ts,tsx}` and Playwright end-to-end tests in `test/` as `*.e2e.test.ts`.** Vitest collects only the first pattern.
36
+ 3. **Component tests need a DOM test environment, and Vitest runs in Node.js.** Add that environment with the first component test.
37
+ 4. **Read configuration through `requireEnvironment` in `src/environment.ts`.** Document each variable in `.env.example`.
38
+ 5. **Start from the accepted spec, in plan mode** (Cursor: Plan Mode). Give the plan the change's `intent/<change>/intent.md` and `spec.md`. Commit the approved plan as `intent/<change>/plan.md` with an `Accepted by:` line naming the engineer, as `.agents/skills/sdlc/playbooks/build.md` describes.
39
+ 6. **Start a bug fix with a failing test.** Reproduce the bug as a test, confirm it fails for the reason you expect, and commit it. Then create `.git/bug-fix-in-progress`, so `.agents/hooks/agent-test-edit-gate.sh` blocks test edits, make the test pass without editing it, and delete `.git/bug-fix-in-progress`.
40
+ 7. **Do not start work a person did not ask for.** When a message reports a problem without asking for work, answer in a few lines and end with the message that would start it: `/sdlc` followed by their own words.
41
+ 8. **Branch from the latest `origin/main`, and open the pull request ready for review.** Name the branch `<type>/<short-description>` and fill the body from `.github/pull_request_template.md`. `.github/workflows/ci.yml` runs full verification only on a pull request that is not a draft. Never merge a pull request: a person merges it with `--squash` after code owner approval, bottom-up for a stack of pull requests.
42
+ 9. **Write replies a person can check.** Reply in the language the person wrote in. Write paths from the project root, such as `README.md:12`, never from the machine's root. State as a fact only what you opened or ran in this turn, and say what you ran; mark anything else as inferred or not checked. Answer what was asked and stop: leave out tools, services, and steps the request does not need, and never hand the person a check you could run. Send nothing outside the session, such as a message to another session or a service, unless a task step says to.
45
43
 
46
44
  ## Things Claude gets wrong
47
45
 
48
46
  When Claude makes a mistake twice, add the correction here.
49
47
 
50
48
  - **Database for `pnpm dev` and end-to-end tests**: both need a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`; the README lists every variable. Run `pnpm exec playwright install chromium` once before the first `pnpm test:e2e`.
51
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It also blocks merging or approving a pull request, approving a deployment, and gh aliases, and asks the person before an irreversible git command such as a force push or a hard reset. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
52
- - **Production gate**: `.agents/hooks/agent-production-gate.sh` blocks a shell command that deploys to `prod` (`gh workflow run` or a workflow dispatch with `environment=prod`), a Railway CLI command that names `prod` with `-e`, `--environment`, or `railway environment`, and a release tag push, unless a release manager started the session with `RELEASE_APPROVAL` set. Report what is ready to promote instead. When a gated command appears only inside a message, write the text to a file with your file-editing tool, not a shell heredoc, and pass it with `git commit -F <file>` or `gh pr create --body-file <file>`. The gate reads only shell commands, so an MCP tool or a Railway command without `-e` or `--environment` passes it. It is a convenience, not a security boundary: the `prod` environment's required reviewers and Railway credentials are the boundary.
53
-
54
- ## Related documentation
55
-
56
- - [README.md](README.md): environment variables, scripts, container, deploy
57
- - [CONTRIBUTING.md](CONTRIBUTING.md): prerequisites, Git hooks, pull requests
49
+ - **Production gate**: `.agents/hooks/agent-production-gate.sh` blocks a shell command that deploys to `prod`, runs a Railway CLI command that names `prod`, or pushes a release tag, unless a release manager started the session with `RELEASE_APPROVAL` set. Report what is ready to promote instead. When a gated command appears only inside a message, write the text to a file with your file-editing tool, not a shell heredoc, and pass it with `git commit -F <file>` or `gh pr create --body-file <file>`. The gate reads only shell commands, so an MCP tool or a Railway command without `-e` or `--environment` passes it.
58
50
 
59
51
  <!-- BEGIN:nextjs-agent-rules -->
60
52
 
@@ -51,6 +51,7 @@ We use trunk-based development. `main` is the only long-lived branch, and every
51
51
  - Branch from `main` and merge back within a day or two. Do not create `develop` or release branches.
52
52
  - Merge unfinished work behind a feature flag or keep it unreachable instead of holding a long-lived branch.
53
53
  - Pull requests are squash-merged, so the pull request title becomes the commit on `main`.
54
+ - After a pull request that only reformats code merges, the next pull request lists its commit on `main` in `.git-blame-ignore-revs` at the repository root, creating the file the first time, with a `#` comment that names the change, as [GitHub Docs](https://docs.github.com/en/repositories/working-with-files/using-files/viewing-and-understanding-files) shows. GitHub then hides that commit in the blame view.
54
55
  - Write commit messages in the format that `@next-friday/commitlint-config-friday` defines. Pull request titles use `<type>(<scope>): <subject>`, which `.github/workflows/validate-pr-title.yml` checks.
55
56
  - Keep each pull request focused on one cohesive change.
56
57
  - Describe observable page, collection, API, or configuration effects.
@@ -22,6 +22,7 @@
22
22
  "generate:importmap": "payload generate:importmap",
23
23
  "generate:types": "payload generate:types",
24
24
  "human-gates:check": "node scripts/check-human-gates.ts",
25
+ "intent:check": "node scripts/check-intent.ts",
25
26
  "knip": "node --env-file-if-exists=.env node_modules/knip/bin/knip.js",
26
27
  "lint": "eslint . --fix --cache --max-warnings=0 --no-inline-config",
27
28
  "lint:check": "eslint . --cache --max-warnings=0 --no-inline-config",
@@ -43,7 +44,7 @@
43
44
  "test:watch": "vitest",
44
45
  "typecheck": "next typegen && tsc --noEmit -p tsconfig.json",
45
46
  "verify": "pnpm verify:static && pnpm test:coverage && pnpm build",
46
- "verify:static": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm human-gates:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm peers:check && pnpm typecheck && pnpm knip && pnpm depcruise"
47
+ "verify:static": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm human-gates:check && pnpm intent:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm peers:check && pnpm typecheck && pnpm knip && pnpm depcruise"
47
48
  },
48
49
  "dependencies": {
49
50
  "@payloadcms/db-postgres": "3.92.1",
@@ -120,6 +120,8 @@ jobs:
120
120
  run: pnpm gates:check
121
121
  - name: Check human gates
122
122
  run: pnpm human-gates:check
123
+ - name: Self-test the intent checker
124
+ run: pnpm intent:check
123
125
  - name: Check lint
124
126
  run: pnpm lint:check
125
127
  - name: Check formatting
@@ -24,7 +24,6 @@ Turborepo workspace in TypeScript on pnpm and Node.js `>=24.22.1 <25`. `apps/app
24
24
  - Lint: `pnpm verify:static` (ESLint allows zero warnings; the dependency check prints `Tasks: 2 successful, 2 total`)
25
25
 
26
26
  Run all three before reporting any task complete, and paste the output. `pnpm verify` runs all three.
27
- If a test fails, fix the code, not the test.
28
27
 
29
28
  ## Architecture
30
29
 
@@ -34,16 +33,15 @@ If a test fails, fix the code, not the test.
34
33
 
35
34
  ## Conventions
36
35
 
37
- 1. **Follow `.agents/rules/`.** `.agents/rules.json` gives each rule's scope; Claude Code and Cursor load them. After changing either, or a skill or subagent in `.agents/skills/` or `.agents/agents/`, run `pnpm rules:sync`; `pnpm check` fails on stale copies.
38
- 2. **Change the backoffice schema only through collections, then regenerate and commit.** Payload generates `apps/backoffice/src/app/(payload)/`, `apps/backoffice/src/payload-types.ts`, and `apps/backoffice/src/migrations/`; run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>`. Do not edit those files by hand.
39
- 3. **Put unit tests next to the code and Playwright end-to-end tests in `apps/app/test/` and `apps/backoffice/test/` as `*.e2e.test.ts`.** Vitest collects `apps/app/app/**/*.test.{ts,tsx}` and `apps/backoffice/src/**/*.test.{ts,tsx}`.
40
- 4. **Component tests need a DOM test environment, and Vitest runs in Node.js.** Add that environment with the first component test.
41
- 5. **Read backoffice configuration through `requireEnvironment` in `apps/backoffice/src/environment.ts`.** Document each variable in `.env.example`.
42
- 6. **Start from the accepted spec, in plan mode.** Claude Code starts every session in plan mode (`.claude/settings.json`); in Cursor, switch to Plan Mode before the first edit. Give the plan the change's `intent/<change>/intent.md` and `spec.md`, and have it name the files that change, the order of the work, and the tests that prove it. Commit the approved plan as `intent/<change>/plan.md`. When implementation departs from the plan, update `plan.md` in the same commit.
43
- 7. **Start a bug fix with a failing test.** Reproduce the bug as a test, run it, and confirm it fails for the reason you expect. Commit that test. Then create `.git/bug-fix-in-progress`, so `.agents/hooks/agent-test-edit-gate.sh` blocks test edits, and make the test pass without editing it. Delete `.git/bug-fix-in-progress` when the fix is done.
44
- 8. **Start work only when a person asks or a trigger runs it, and stop only at the human gates, before an irreversible action, or for a decision only a person can make.** A question or a statement gets an answer, not a file, a commit, or a pull request. When a message reports a problem without asking for work, answer in a few lines and end with the message that would start the work: `/sdlc` followed by their own words. Once a task starts, carry it to the next gate without asking; `.agents/rules/agent-owned-work.md` lists the gates.
45
- 9. **Branch from the latest `origin/main`, and open the pull request ready for review.** Name the branch `<type>/<short-description>` and fill the body from `.github/pull_request_template.md`. `.github/workflows/ci.yml` runs full verification only on a pull request that is not a draft. Drive it until it is green and waits only on code owner approval, as `.agents/skills/sdlc/playbooks/review.md` describes. Rebase and `git push --force-with-lease` only branches you own. Never merge a pull request: a person merges it with `--squash` after code owner approval, bottom-up for a stack of pull requests.
46
- 10. **Write replies a person can check.** Reply in the language the person wrote in. Write paths from the project root, such as `README.md:12`, never from the machine's root. State as a fact only what you opened or ran in this turn, and say what you ran; mark anything else as inferred or not checked. Answer what was asked and stop: leave out tools, services, and steps the request does not need, and never hand the person a check you could run. Send nothing outside the session, such as a message to another session or a service, unless a task step says to.
36
+ 1. **Change the backoffice schema only through collections, then regenerate and commit.** Payload generates `apps/backoffice/src/app/(payload)/`, `apps/backoffice/src/payload-types.ts`, and `apps/backoffice/src/migrations/`; run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>`. Do not edit those files by hand.
37
+ 2. **Put unit tests next to the code and Playwright end-to-end tests in `apps/app/test/` and `apps/backoffice/test/` as `*.e2e.test.ts`.** Vitest collects `apps/app/app/**/*.test.{ts,tsx}` and `apps/backoffice/src/**/*.test.{ts,tsx}`.
38
+ 3. **Component tests need a DOM test environment, and Vitest runs in Node.js.** Add that environment with the first component test.
39
+ 4. **Read backoffice configuration through `requireEnvironment` in `apps/backoffice/src/environment.ts`.** Document each variable in `.env.example`.
40
+ 5. **Start from the accepted spec, in plan mode** (Cursor: Plan Mode). Give the plan the change's `intent/<change>/intent.md` and `spec.md`. Commit the approved plan as `intent/<change>/plan.md` with an `Accepted by:` line naming the engineer, as `.agents/skills/sdlc/playbooks/build.md` describes.
41
+ 6. **Start a bug fix with a failing test.** Reproduce the bug as a test, confirm it fails for the reason you expect, and commit it. Then create `.git/bug-fix-in-progress`, so `.agents/hooks/agent-test-edit-gate.sh` blocks test edits, make the test pass without editing it, and delete `.git/bug-fix-in-progress`.
42
+ 7. **Do not start work a person did not ask for.** When a message reports a problem without asking for work, answer in a few lines and end with the message that would start it: `/sdlc` followed by their own words.
43
+ 8. **Branch from the latest `origin/main`, and open the pull request ready for review.** Name the branch `<type>/<short-description>` and fill the body from `.github/pull_request_template.md`. `.github/workflows/ci.yml` runs full verification only on a pull request that is not a draft. Never merge a pull request: a person merges it with `--squash` after code owner approval, bottom-up for a stack of pull requests.
44
+ 9. **Write replies a person can check.** Reply in the language the person wrote in. Write paths from the project root, such as `README.md:12`, never from the machine's root. State as a fact only what you opened or ran in this turn, and say what you ran; mark anything else as inferred or not checked. Answer what was asked and stop: leave out tools, services, and steps the request does not need, and never hand the person a check you could run. Send nothing outside the session, such as a message to another session or a service, unless a task step says to.
47
45
 
48
46
  ## Things Claude gets wrong
49
47
 
@@ -51,10 +49,4 @@ When Claude makes a mistake twice, add the correction here.
51
49
 
52
50
  - **Next.js docs live per app**: this Next.js version differs from your training data. Read the guide in `apps/app/node_modules/next/dist/docs/` or `apps/backoffice/node_modules/next/dist/docs/` before writing Next.js code; the workspace root has no `next` package.
53
51
  - **Database for `pnpm dev` and end-to-end tests**: the backoffice needs a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`; the README lists every variable. Run `pnpm --filter ./apps/app exec playwright install chromium` once before the first `pnpm test:e2e`.
54
- - **Agent shell gate**: `.agents/hooks/agent-shell-gate.sh` blocks a shell command that writes to a protected path such as `.agents`, `.cursor`, `.claude/rules`, or `.husky`. It also blocks merging or approving a pull request, approving a deployment, and gh aliases, and asks the person before an irreversible git command such as a force push or a hard reset. It is a convenience, not a security boundary: CI and code-owner review are the boundary.
55
- - **Production gate**: `.agents/hooks/agent-production-gate.sh` blocks a shell command that deploys to `prod` (`gh workflow run` or a workflow dispatch with `environment=prod`), a Railway CLI command that names `prod` with `-e`, `--environment`, or `railway environment`, and a release tag push, unless a release manager started the session with `RELEASE_APPROVAL` set. Report what is ready to promote instead. When a gated command appears only inside a message, write the text to a file with your file-editing tool, not a shell heredoc, and pass it with `git commit -F <file>` or `gh pr create --body-file <file>`. The gate reads only shell commands, so an MCP tool or a Railway command without `-e` or `--environment` passes it. It is a convenience, not a security boundary: the `prod` environment's required reviewers and Railway credentials are the boundary.
56
-
57
- ## Related documentation
58
-
59
- - [README.md](README.md): environment variables, scripts, CI caching, container, deploy
60
- - [CONTRIBUTING.md](CONTRIBUTING.md): prerequisites, Git hooks, pull requests
52
+ - **Production gate**: `.agents/hooks/agent-production-gate.sh` blocks a shell command that deploys to `prod`, runs a Railway CLI command that names `prod`, or pushes a release tag, unless a release manager started the session with `RELEASE_APPROVAL` set. Report what is ready to promote instead. When a gated command appears only inside a message, write the text to a file with your file-editing tool, not a shell heredoc, and pass it with `git commit -F <file>` or `gh pr create --body-file <file>`. The gate reads only shell commands, so an MCP tool or a Railway command without `-e` or `--environment` passes it.
@@ -51,6 +51,7 @@ We use trunk-based development. `main` is the only long-lived branch, and every
51
51
  - Branch from `main` and merge back within a day or two. Do not create `develop` or release branches.
52
52
  - Merge unfinished work behind a feature flag or keep it unreachable instead of holding a long-lived branch.
53
53
  - Pull requests are squash-merged, so the pull request title becomes the commit on `main`.
54
+ - After a pull request that only reformats code merges, the next pull request lists its commit on `main` in `.git-blame-ignore-revs` at the repository root, creating the file the first time, with a `#` comment that names the change, as [GitHub Docs](https://docs.github.com/en/repositories/working-with-files/using-files/viewing-and-understanding-files) shows. GitHub then hides that commit in the blame view.
54
55
  - Write commit messages in the format that `@next-friday/commitlint-config-friday` defines. Pull request titles use `<type>(<scope>): <subject>`, which `.github/workflows/validate-pr-title.yml` checks.
55
56
  - Keep each pull request focused on one cohesive change.
56
57
  - Describe observable page, collection, API, or configuration effects.
@@ -22,6 +22,7 @@
22
22
  "generate:importmap": "pnpm --filter ./apps/backoffice generate:importmap",
23
23
  "generate:types": "pnpm --filter ./apps/backoffice generate:types",
24
24
  "human-gates:check": "node scripts/check-human-gates.ts",
25
+ "intent:check": "node scripts/check-intent.ts",
25
26
  "knip": "knip",
26
27
  "lint": "eslint . --fix --cache --max-warnings=0 --no-inline-config",
27
28
  "lint:check": "eslint . --cache --max-warnings=0 --no-inline-config",
@@ -42,7 +43,7 @@
42
43
  "test:watch": "turbo run test:watch --filter=./apps/*",
43
44
  "typecheck": "tsc --noEmit -p tsconfig.json && turbo run typecheck ${TURBO_FILTER:-\"--filter=./apps/*\"}",
44
45
  "verify": "pnpm verify:static && pnpm test:coverage && pnpm build",
45
- "verify:static": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm human-gates:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm peers:check && pnpm typecheck && pnpm knip && pnpm depcruise"
46
+ "verify:static": "pnpm suppressions:check && pnpm rules:check && pnpm gates:check && pnpm human-gates:check && pnpm intent:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm peers:check && pnpm typecheck && pnpm knip && pnpm depcruise"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@commitlint/cli": "21.2.4",