@next-friday/create-app 9.1.1 → 9.2.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 (324) hide show
  1. package/README.md +5 -4
  2. package/dist/main.mjs +135 -96
  3. package/package.json +14 -10
  4. package/templates/base/.agents/hooks/agent-mcp-gate.sh +7 -2
  5. package/templates/base/.agents/hooks/agent-production-gate.sh +6 -1
  6. package/templates/base/.agents/hooks/agent-shell-gate.sh +1 -181
  7. package/templates/base/.agents/hooks/agent-test-edit-gate.sh +12 -3
  8. package/templates/base/.agents/review.md +2 -2
  9. package/templates/base/.agents/rules/no-suppression.md +1 -1
  10. package/templates/base/.agents/skill-evals/README.md +42 -0
  11. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/case.yaml +11 -0
  12. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/01-the-reply-explains-why-pnpm.md +7 -0
  13. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/02-no-file-in-the-project.md +7 -0
  14. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/03-no-commit-is-made-nothing.md +7 -0
  15. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/05-every-path-in-the-reply.md +7 -0
  16. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/06-everything-the-reply-states-as.md +7 -0
  17. package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/prompt.md +8 -0
  18. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/case.yaml +11 -0
  19. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/fixture.md +1 -0
  20. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/01-work-happens-on-the-plan-branch.md +7 -0
  21. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/02-the-plan-is-implemented-and-checked.md +7 -0
  22. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/03-the-branch-is-pushed.md +7 -0
  23. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/04-the-reply-lists-three-playbooks.md +7 -0
  24. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/05-no-approval-and-no-merge.md +7 -0
  25. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/06-the-reply-ends-at-the-code-owner.md +7 -0
  26. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/07-the-plan-names-the-engineer.md +7 -0
  27. package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/prompt.md +8 -0
  28. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/case.yaml +70 -0
  29. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/fixture.md +1 -0
  30. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/01-the-reply-asks-numbered-questions.md +7 -0
  31. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/02-no-plan-before-the-answers.md +7 -0
  32. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/03-no-question-depends-on-another.md +7 -0
  33. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/04-no-file-or-commit.md +7 -0
  34. package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/prompt.md +8 -0
  35. package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/case.yaml +67 -0
  36. package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/fixture.md +1 -0
  37. package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/graders/01-the-plan-has-the-four-headings.md +7 -0
  38. package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/graders/02-no-source-file-or-commit.md +7 -0
  39. package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/graders/03-the-reply-names-the-gate.md +7 -0
  40. package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/prompt.md +10 -0
  41. package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/case.yaml +7 -0
  42. package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/fixture.md +1 -0
  43. package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/graders/01-no-deployment-is-started.md +7 -0
  44. package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/graders/02-the-reply-names-the-release-manager-gate.md +7 -0
  45. package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/graders/03-the-reply-says-what-it-could-not-read.md +7 -0
  46. package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/prompt.md +8 -0
  47. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/case.yaml +12 -0
  48. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/01-a-file-intentkebabcasenameintentmd-exists-with.md +7 -0
  49. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/02-the-reply-shows-the-draft.md +7 -0
  50. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/03-no-commit-is-made-nothing.md +7 -0
  51. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/04-reply-lists-the-playbook-steps.md +7 -0
  52. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/06-every-path-in-the-reply.md +7 -0
  53. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/07-the-drafts-open-questions-section.md +7 -0
  54. package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/prompt.md +10 -0
  55. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/case.yaml +33 -0
  56. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/fixture.md +1 -0
  57. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/graders/01-the-reply-shows-the-reproduction-output.md +7 -0
  58. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/graders/02-the-reply-names-one-cause-with-evidence.md +7 -0
  59. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/graders/03-the-plan-has-the-four-headings.md +7 -0
  60. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/graders/04-no-file-or-commit.md +7 -0
  61. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/graders/05-the-reply-names-the-gate.md +7 -0
  62. package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/prompt.md +8 -0
  63. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/case.yaml +11 -0
  64. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/01-the-first-message-restates-the.md +7 -0
  65. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/02-the-reply-asks-numbered-questions.md +7 -0
  66. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/03-no-intentmd-is-written-before.md +7 -0
  67. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/04-reply-lists-the-playbook-steps.md +7 -0
  68. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/05-no-commit-is-made-nothing.md +7 -0
  69. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/07-every-path-in-the-reply.md +7 -0
  70. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/08-no-question-in-the-round.md +7 -0
  71. package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/prompt.md +8 -0
  72. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/case.yaml +14 -0
  73. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/fixture.md +1 -0
  74. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/01-the-intent-has-the-five-headings.md +7 -0
  75. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/02-problem-holds-the-error-and-where.md +7 -0
  76. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/03-unverified-cause-is-an-open-question.md +7 -0
  77. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/04-no-source-file-is-changed.md +7 -0
  78. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/05-a-branch-is-pushed-and-the-gate-is-named.md +7 -0
  79. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/06-the-person-is-asked-no-question.md +7 -0
  80. package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/prompt.md +8 -0
  81. package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/case.yaml +11 -0
  82. package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/01-the-reply-follows-the-plan.md +7 -0
  83. package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/02-the-reply-does-not-tell.md +7 -0
  84. package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/03-no-file-is-created-or.md +7 -0
  85. package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/05-every-path-in-the-reply.md +7 -0
  86. package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/prompt.md +8 -0
  87. package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/case.yaml +10 -0
  88. package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/fixture.md +1 -0
  89. package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/graders/01-no-file-is-written-and-nothing-is-committed.md +7 -0
  90. package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/graders/02-the-reply-names-the-closest-row.md +7 -0
  91. package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/graders/03-the-reply-is-short.md +7 -0
  92. package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/prompt.md +8 -0
  93. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/case.yaml +79 -0
  94. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/fixture.md +1 -0
  95. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/01-findings-have-pass-severity-and-location.md +7 -0
  96. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/02-no-approval-and-no-merge.md +7 -0
  97. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/03-the-reply-names-the-code-owner-gate.md +7 -0
  98. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/04-nothing-is-pushed-or-changed.md +7 -0
  99. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/05-the-review-runs-in-a-fresh-context.md +7 -0
  100. package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/prompt.md +8 -0
  101. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/case.yaml +41 -0
  102. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/fixture.md +1 -0
  103. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/01-no-spec-is-written.md +7 -0
  104. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/02-no-commit-is-made.md +7 -0
  105. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/03-the-reply-says-not-merged.md +7 -0
  106. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/05-the-reply-is-short.md +7 -0
  107. package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/prompt.md +8 -0
  108. package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/case.yaml +11 -0
  109. package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/01-no-intentmd-or-any-other.md +7 -0
  110. package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/02-no-commit-is-made-nothing.md +7 -0
  111. package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/04-every-path-in-the-reply.md +7 -0
  112. package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/05-the-reply-says-that-work.md +7 -0
  113. package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/prompt.md +8 -0
  114. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/case.yaml +41 -0
  115. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/fixture.md +1 -0
  116. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/01-the-spec-has-the-five-headings.md +7 -0
  117. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/02-policies-has-one-line-per-policy.md +7 -0
  118. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/03-no-policy-is-called-unwritten.md +7 -0
  119. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/04-a-branch-is-pushed-for-review.md +7 -0
  120. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/05-the-reply-names-the-gate.md +7 -0
  121. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/07-no-merge-is-made.md +7 -0
  122. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/08-the-four-policies-are-read-before-writing.md +7 -0
  123. package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/prompt.md +8 -0
  124. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/case.yaml +10 -0
  125. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/01-the-reply-says-that-work.md +7 -0
  126. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/02-the-reply-gives-one-example.md +7 -0
  127. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/03-the-reply-lists-the-project.md +7 -0
  128. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/04-no-file-is-created-or.md +7 -0
  129. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/06-every-path-in-the-reply.md +7 -0
  130. package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/prompt.md +8 -0
  131. package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/case.yaml +9 -0
  132. package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/01-the-reply-says-that-this.md +7 -0
  133. package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/02-the-reply-does-not-describe.md +7 -0
  134. package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/03-no-file-is-created-or.md +7 -0
  135. package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/05-every-path-in-the-reply.md +7 -0
  136. package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/prompt.md +8 -0
  137. package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/case.yaml +10 -0
  138. package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/01-the-reply-says-to-send.md +7 -0
  139. package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/02-no-file-is-created-or.md +7 -0
  140. package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/04-every-path-in-the-reply.md +7 -0
  141. package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/prompt.md +8 -0
  142. package/templates/base/.agents/skills/sdlc/SKILL.md +25 -21
  143. package/templates/base/.agents/skills/sdlc/playbooks/build.md +14 -9
  144. package/templates/base/.agents/skills/sdlc/playbooks/deploy.md +2 -2
  145. package/templates/base/.agents/skills/sdlc/playbooks/design.md +3 -3
  146. package/templates/base/.agents/skills/sdlc/playbooks/fix.md +23 -0
  147. package/templates/base/.agents/skills/sdlc/playbooks/maintain.md +3 -4
  148. package/templates/base/.agents/skills/sdlc/playbooks/open-pr.md +3 -3
  149. package/templates/base/.agents/skills/sdlc/playbooks/plan.md +3 -3
  150. package/templates/base/.agents/skills/sdlc/playbooks/review.md +2 -2
  151. package/templates/base/.agents/skills/sdlc-help/SKILL.md +4 -2
  152. package/templates/base/.claude/managed-settings.example.json +2 -2
  153. package/templates/base/.claude/settings.json +0 -13
  154. package/templates/base/.claude/skills/sdlc/SKILL.md +25 -21
  155. package/templates/base/.claude/skills/sdlc/playbooks/build.md +14 -9
  156. package/templates/base/.claude/skills/sdlc/playbooks/deploy.md +2 -2
  157. package/templates/base/.claude/skills/sdlc/playbooks/design.md +3 -3
  158. package/templates/base/.claude/skills/sdlc/playbooks/fix.md +23 -0
  159. package/templates/base/.claude/skills/sdlc/playbooks/maintain.md +3 -4
  160. package/templates/base/.claude/skills/sdlc/playbooks/open-pr.md +3 -3
  161. package/templates/base/.claude/skills/sdlc/playbooks/plan.md +3 -3
  162. package/templates/base/.claude/skills/sdlc/playbooks/review.md +2 -2
  163. package/templates/base/.claude/skills/sdlc-help/SKILL.md +4 -2
  164. package/templates/base/.cursor/hooks.json +0 -6
  165. package/templates/base/.cursor/rules/no-suppression.mdc +1 -1
  166. package/templates/base/.cursor/skills/sdlc/SKILL.md +25 -21
  167. package/templates/base/.cursor/skills/sdlc/playbooks/build.md +14 -9
  168. package/templates/base/.cursor/skills/sdlc/playbooks/deploy.md +2 -2
  169. package/templates/base/.cursor/skills/sdlc/playbooks/design.md +3 -3
  170. package/templates/base/.cursor/skills/sdlc/playbooks/fix.md +23 -0
  171. package/templates/base/.cursor/skills/sdlc/playbooks/maintain.md +3 -4
  172. package/templates/base/.cursor/skills/sdlc/playbooks/open-pr.md +3 -3
  173. package/templates/base/.cursor/skills/sdlc/playbooks/plan.md +3 -3
  174. package/templates/base/.cursor/skills/sdlc/playbooks/review.md +2 -2
  175. package/templates/base/.cursor/skills/sdlc-help/SKILL.md +4 -2
  176. package/templates/base/.github/ISSUE_TEMPLATE/documentation.yml +1 -1
  177. package/templates/base/.github/dependabot.yml +1 -10
  178. package/templates/base/.github/file-filters.yml +3 -6
  179. package/templates/base/.github/workflows/agent-evals.yml +46 -0
  180. package/templates/base/.github/workflows/claude-fix-loop.yml +45 -0
  181. package/templates/base/.github/workflows/control-band.yml +115 -0
  182. package/templates/base/.github/workflows/dependency-review.yml +1 -0
  183. package/templates/base/.github/workflows/deploy.yml +4 -2
  184. package/templates/base/.github/workflows/osv-scanner.yml +0 -5
  185. package/templates/base/.github/workflows/pr-triage.yml +1 -1
  186. package/templates/base/.github/workflows/secret-scan.yml +4 -1
  187. package/templates/base/.github/workflows/spec-on-intent-merge.yml +108 -0
  188. package/templates/base/.github/workflows/validate-pr-title.yml +3 -2
  189. package/templates/base/.husky/pre-push +1 -8
  190. package/templates/base/REVIEW.md +2 -2
  191. package/templates/base/SETUP.md +44 -8
  192. package/templates/base/bands.yaml +3 -3
  193. package/templates/base/intent/README.md +1 -0
  194. package/templates/base/knip.json +2 -1
  195. package/templates/base/pnpm-workspace.yaml +1 -22
  196. package/templates/base/runbooks/rollback-deploy.md +27 -0
  197. package/templates/base/scripts/check-agent-gates.ts +265 -226
  198. package/templates/base/scripts/check-bands.ts +665 -0
  199. package/templates/base/scripts/check-plan.ts +1047 -0
  200. package/templates/base/scripts/measure-loop.ts +293 -0
  201. package/templates/base/scripts/run-agent-evals.ts +1197 -0
  202. package/templates/base/scripts/sync-agent-rules.ts +0 -8
  203. package/templates/nestjs/.dependency-cruiser.json +1 -1
  204. package/templates/nestjs/.github/ISSUE_TEMPLATE/bug.yml +5 -5
  205. package/templates/nestjs/.github/workflows/ci.yml +58 -9
  206. package/templates/nestjs/.github/workflows/sast.yml +0 -5
  207. package/templates/nestjs/AGENTS.md +17 -13
  208. package/templates/nestjs/CONTRIBUTING.md +3 -2
  209. package/templates/nestjs/Dockerfile +4 -4
  210. package/templates/nestjs/README.md +4 -6
  211. package/templates/nestjs/_gitignore +0 -1
  212. package/templates/nestjs/package.json +21 -19
  213. package/templates/nestjs/src/app.controller.test.ts +1 -0
  214. package/templates/nestjs/src/health/health.controller.test.ts +1 -0
  215. package/templates/nestjs/src/port.test.ts +1 -0
  216. package/templates/nestjs/test/app.e2e.test.ts +1 -0
  217. package/templates/nestjs/tsconfig.build.json +2 -3
  218. package/templates/nestjs/tsconfig.json +1 -3
  219. package/templates/nestjs/vitest.config.ts +0 -1
  220. package/templates/nestjs/vitest.e2e.config.ts +0 -1
  221. package/templates/nextjs/.dependency-cruiser.json +1 -1
  222. package/templates/nextjs/.github/ISSUE_TEMPLATE/bug.yml +1 -1
  223. package/templates/nextjs/.github/workflows/ci.yml +58 -9
  224. package/templates/nextjs/.github/workflows/sast.yml +0 -5
  225. package/templates/nextjs/AGENTS.md +17 -13
  226. package/templates/nextjs/CONTRIBUTING.md +3 -2
  227. package/templates/nextjs/Dockerfile +2 -2
  228. package/templates/nextjs/README.md +5 -3
  229. package/templates/nextjs/app/layout.tsx +2 -2
  230. package/templates/nextjs/app/page.test.ts +1 -1
  231. package/templates/nextjs/app/page.tsx +1 -1
  232. package/templates/nextjs/package.json +15 -14
  233. package/templates/nextjs/test/home.e2e.test.ts +3 -7
  234. package/templates/nextjs/tsconfig.json +0 -3
  235. package/templates/nodejs/.dependency-cruiser.json +1 -1
  236. package/templates/nodejs/.github/ISSUE_TEMPLATE/bug.yml +5 -5
  237. package/templates/nodejs/.github/workflows/ci.yml +58 -9
  238. package/templates/nodejs/.github/workflows/sast.yml +0 -5
  239. package/templates/nodejs/AGENTS.md +17 -12
  240. package/templates/nodejs/CONTRIBUTING.md +4 -3
  241. package/templates/nodejs/Dockerfile +3 -3
  242. package/templates/nodejs/README.md +4 -4
  243. package/templates/nodejs/_gitignore +0 -1
  244. package/templates/nodejs/package.json +13 -11
  245. package/templates/nodejs/src/server.test.ts +23 -0
  246. package/templates/nodejs/src/server.ts +2 -2
  247. package/templates/nodejs/tsconfig.build.json +2 -3
  248. package/templates/nodejs/tsconfig.json +0 -4
  249. package/templates/payload/.agents/agents/verifier.md +1 -1
  250. package/templates/payload/.agents/review.md +21 -0
  251. package/templates/payload/.claude/agents/verifier.md +1 -1
  252. package/templates/payload/.cursor/agents/verifier.md +1 -1
  253. package/templates/payload/.dependency-cruiser.json +1 -1
  254. package/templates/payload/.github/ISSUE_TEMPLATE/bug.yml +1 -1
  255. package/templates/payload/.github/workflows/ci.yml +75 -10
  256. package/templates/payload/.github/workflows/sast.yml +0 -5
  257. package/templates/payload/AGENTS.md +22 -18
  258. package/templates/payload/CONTRIBUTING.md +4 -3
  259. package/templates/payload/Dockerfile +2 -2
  260. package/templates/payload/README.md +8 -4
  261. package/templates/payload/REVIEW.md +21 -0
  262. package/templates/payload/package.json +17 -15
  263. package/templates/payload/src/app/(frontend)/layout.tsx +2 -2
  264. package/templates/payload/src/app/(frontend)/page.test.ts +1 -1
  265. package/templates/payload/src/app/(frontend)/page.tsx +1 -1
  266. package/templates/payload/src/app/favicon.ico +0 -0
  267. package/templates/payload/src/app/health/route.test.ts +20 -2
  268. package/templates/payload/src/app/health/route.ts +9 -2
  269. package/templates/payload/src/collections/media.test.ts +36 -1
  270. package/templates/payload/src/collections/media.ts +1 -1
  271. package/templates/payload/src/payload.config.test.ts +15 -0
  272. package/templates/payload/test/home.e2e.test.ts +3 -7
  273. package/templates/payload/tsconfig.json +0 -1
  274. package/templates/turborepo/.agents/agents/verifier.md +1 -1
  275. package/templates/turborepo/.agents/review.md +21 -0
  276. package/templates/turborepo/.claude/agents/verifier.md +1 -1
  277. package/templates/turborepo/.cursor/agents/verifier.md +1 -1
  278. package/templates/turborepo/.dockerignore +9 -4
  279. package/templates/turborepo/.github/ISSUE_TEMPLATE/bug.yml +16 -1
  280. package/templates/turborepo/.github/dependabot.yml +1 -10
  281. package/templates/turborepo/.github/scripts/affected-apps.sh +5 -23
  282. package/templates/turborepo/.github/workflows/ci.yml +140 -103
  283. package/templates/turborepo/.github/workflows/deploy.yml +24 -23
  284. package/templates/turborepo/.github/workflows/sast.yml +0 -5
  285. package/templates/turborepo/AGENTS.md +22 -18
  286. package/templates/turborepo/CONTRIBUTING.md +6 -4
  287. package/templates/turborepo/README.md +8 -8
  288. package/templates/turborepo/REVIEW.md +21 -0
  289. package/templates/turborepo/apps/app/.dependency-cruiser.json +1 -1
  290. package/templates/turborepo/apps/app/AGENTS.md +9 -0
  291. package/templates/turborepo/apps/app/Dockerfile +2 -2
  292. package/templates/turborepo/apps/app/app/layout.tsx +2 -2
  293. package/templates/turborepo/apps/app/app/page.test.ts +1 -1
  294. package/templates/turborepo/apps/app/app/page.tsx +1 -1
  295. package/templates/turborepo/apps/app/package.json +9 -9
  296. package/templates/turborepo/apps/app/test/home.e2e.test.ts +3 -7
  297. package/templates/turborepo/apps/app/tsconfig.json +0 -3
  298. package/templates/turborepo/apps/backoffice/.dependency-cruiser.json +1 -1
  299. package/templates/turborepo/apps/backoffice/AGENTS.md +9 -0
  300. package/templates/turborepo/apps/backoffice/Dockerfile +2 -2
  301. package/templates/turborepo/apps/backoffice/package.json +12 -11
  302. package/templates/turborepo/apps/backoffice/src/app/(frontend)/layout.tsx +2 -2
  303. package/templates/turborepo/apps/backoffice/src/app/(frontend)/page.test.ts +1 -1
  304. package/templates/turborepo/apps/backoffice/src/app/(frontend)/page.tsx +1 -1
  305. package/templates/turborepo/apps/backoffice/src/app/favicon.ico +0 -0
  306. package/templates/turborepo/apps/backoffice/src/app/health/route.test.ts +20 -2
  307. package/templates/turborepo/apps/backoffice/src/app/health/route.ts +10 -2
  308. package/templates/turborepo/apps/backoffice/src/collections/media.test.ts +36 -1
  309. package/templates/turborepo/apps/backoffice/src/collections/media.ts +1 -1
  310. package/templates/turborepo/apps/backoffice/src/environment.test.ts +19 -0
  311. package/templates/turborepo/apps/backoffice/src/payload.config.test.ts +15 -0
  312. package/templates/turborepo/apps/backoffice/test/home.e2e.test.ts +3 -7
  313. package/templates/turborepo/apps/backoffice/tsconfig.json +0 -1
  314. package/templates/turborepo/knip.json +4 -2
  315. package/templates/turborepo/package.json +16 -16
  316. package/templates/turborepo/pnpm-workspace.yaml +1 -22
  317. package/templates/turborepo/turbo.json +32 -11
  318. package/templates/base/.agents/hooks/agent-suppression-gate.sh +0 -45
  319. package/templates/base/.claude/rules/agents-guide.md +0 -1
  320. package/templates/base/scripts/check-human-gates.ts +0 -383
  321. package/templates/base/scripts/check-intent.ts +0 -391
  322. package/templates/nextjs/knip.json +0 -4
  323. package/templates/payload/src/collections/users.test.ts +0 -10
  324. package/templates/turborepo/apps/backoffice/src/collections/users.test.ts +0 -10
@@ -2,7 +2,7 @@
2
2
  "name": "next-friday-template-nodejs",
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
- "description": "Next Friday Node.js template.",
5
+ "description": "Node.js HTTP service without a framework.",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/next-friday/next-friday-template-nodejs.git"
@@ -11,44 +11,45 @@
11
11
  "author": "Next Friday",
12
12
  "type": "module",
13
13
  "scripts": {
14
+ "bands:check": "node scripts/check-bands.ts",
14
15
  "build": "tsc -p tsconfig.build.json",
15
16
  "check": "pnpm verify:static && pnpm test:changed && pnpm build",
16
- "clean": "rm -rf dist coverage *.tsbuildinfo .eslintcache node_modules/.cache",
17
+ "clean": "rm -rf dist coverage .eslintcache node_modules/.cache",
17
18
  "depcruise": "depcruise --config .dependency-cruiser.json src eslint.config.ts vitest.config.ts",
19
+ "evals:run": "node scripts/run-agent-evals.ts",
18
20
  "format": "prettier --write --cache .",
19
21
  "format:check": "prettier --check --cache . && editorconfig-checker",
20
22
  "gates:check": "node scripts/check-agent-gates.ts",
21
- "human-gates:check": "node scripts/check-human-gates.ts",
22
- "intent:check": "node scripts/check-intent.ts",
23
23
  "knip": "knip",
24
24
  "lint": "eslint . --fix --cache --max-warnings=0 --no-inline-config",
25
25
  "lint:check": "eslint . --cache --max-warnings=0 --no-inline-config",
26
- "peers:check": "pnpm peers check",
26
+ "loop:measure": "node scripts/measure-loop.ts",
27
+ "plan:check": "node scripts/check-plan.ts",
27
28
  "prepare": "husky",
28
29
  "rules:check": "node scripts/sync-agent-rules.ts --check",
29
30
  "rules:sync": "node scripts/sync-agent-rules.ts",
30
31
  "sort-package-json": "sort-package-json package.json",
31
32
  "sort-package-json:check": "sort-package-json --check package.json",
32
- "start": "node --env-file-if-exists=.env dist/main.js",
33
+ "start": "pnpm build && node --env-file-if-exists=.env dist/main.js",
33
34
  "start:dev": "node --env-file-if-exists=.env --watch src/main.ts",
34
35
  "start:prod": "node dist/main.js",
35
- "suppressions:check": "bash .agents/hooks/agent-suppression-gate.sh --repo",
36
36
  "test": "vitest run --passWithNoTests",
37
37
  "test:changed": "if git rev-parse --quiet --verify origin/main > /dev/null && git diff --quiet \"$(git merge-base origin/main HEAD)\" -- pnpm-lock.yaml pnpm-workspace.yaml \"*package.json\" \"*tsconfig.json\" .husky; then vitest run --changed origin/main --passWithNoTests; else vitest run --passWithNoTests; fi",
38
38
  "test:coverage": "vitest run --coverage --passWithNoTests",
39
39
  "test:watch": "vitest",
40
40
  "typecheck": "tsc --noEmit -p tsconfig.json",
41
41
  "verify": "pnpm verify:static && pnpm test:coverage && pnpm build",
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
+ "verify:static": "pnpm rules:check && pnpm gates:check && pnpm plan:check && pnpm bands:check && pnpm lint:check && pnpm format:check && pnpm sort-package-json:check && pnpm typecheck && pnpm knip && pnpm depcruise"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@commitlint/cli": "21.2.4",
46
46
  "@next-friday/commitlint-config-friday": "4.0.0",
47
47
  "@next-friday/eslint-config-friday": "5.1.0",
48
48
  "@next-friday/prettier-config-friday": "4.0.0",
49
+ "@swc/core": "1.16.22",
49
50
  "@types/node": "26.6.6",
50
- "@vitest/coverage-v8": "5.0.5",
51
- "dependency-cruiser": "18.7.1",
51
+ "@vitest/coverage-v8": "5.1.0",
52
+ "dependency-cruiser": "18.7.2",
52
53
  "editorconfig-checker": "7.0.0",
53
54
  "eslint": "10.14.0",
54
55
  "fast-check": "4.10.2",
@@ -59,7 +60,8 @@
59
60
  "prettier": "3.9.10",
60
61
  "sort-package-json": "4.1.0",
61
62
  "typescript": "7.0.2",
62
- "vitest": "5.0.5"
63
+ "vitest": "5.1.0",
64
+ "yaml": "2.9.1"
63
65
  },
64
66
  "packageManager": "pnpm@12.6.0+sha512.3ef68f951cb111ac204b4a5a16f0b2ddf0da56a96e0413e81d855d9f0b55ef926714709028e1cd00c405c2c5fb7b9e8ec4dc46777c805d0373c2f2ff00fd20ec",
65
67
  "engines": {
@@ -1,3 +1,4 @@
1
+ import {connect} from "node:net";
1
2
  import {describe, expect, it} from "vitest";
2
3
  import {once} from "node:events";
3
4
  import type {AddressInfo} from "node:net";
@@ -57,4 +58,26 @@ describe("createAppServer", () => {
57
58
 
58
59
  expect(response.status).toBe(404);
59
60
  });
61
+
62
+ it("returns 404 for a request target that is not a valid URL", async () => {
63
+ const server = createAppServer();
64
+
65
+ server.listen(0, "127.0.0.1");
66
+ await once(server, "listening");
67
+
68
+ const {port} = server.address() as AddressInfo;
69
+ const socket = connect(port, "127.0.0.1");
70
+
71
+ socket.end("GET // HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n");
72
+
73
+ const chunks: Buffer[] = [];
74
+
75
+ for await (const chunk of socket) {
76
+ chunks.push(chunk as Buffer);
77
+ }
78
+
79
+ server.close();
80
+ await once(server, "close");
81
+ expect(Buffer.concat(chunks).toString()).toMatch(/^HTTP\/1\.1 404 /);
82
+ });
60
83
  });
@@ -2,12 +2,12 @@ import {createServer} from "node:http";
2
2
  import type {Server} from "node:http";
3
3
 
4
4
  /**
5
- * Create the HTTP server. `GET` or `HEAD` `/health` reports that the process is up; every other request gets 404.
5
+ * Create the HTTP server. `GET` or `HEAD` `/health` reports that the process is up; every other request, including one whose target is not a valid URL, gets 404.
6
6
  * @returns A server that is not listening yet.
7
7
  */
8
8
  export function createAppServer(): Server {
9
9
  return createServer((request, response) => {
10
- const {pathname} = new URL(request.url ?? "/", "http://localhost");
10
+ const pathname = URL.parse(request.url ?? "/", "http://localhost")?.pathname;
11
11
 
12
12
  if (pathname === "/health" && (request.method === "GET" || request.method === "HEAD")) {
13
13
  response.writeHead(200, {
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
3
  "compilerOptions": {
4
- "rootDir": "./src",
5
- "types": ["node"]
4
+ "rootDir": "./src"
6
5
  },
7
6
  "include": ["src"],
8
- "exclude": ["node_modules", "test", "dist", "**/*.test.ts"]
7
+ "exclude": ["node_modules", "dist", "**/*.test.ts"]
9
8
  }
@@ -4,14 +4,10 @@
4
4
  "module": "nodenext",
5
5
  "isolatedModules": true,
6
6
  "removeComments": true,
7
- "incremental": true,
8
- "resolveJsonModule": true,
9
7
  "skipLibCheck": true,
10
- "sourceMap": true,
11
8
  "outDir": "./dist",
12
9
  "rootDir": ".",
13
10
  "types": ["node"],
14
- "strict": true,
15
11
  "rewriteRelativeImportExtensions": true
16
12
  },
17
13
  "include": ["**/*.ts"],
@@ -1 +1 @@
1
- Start the app with `pnpm dev`. Exercise the changed behavior and the two nearest neighboring flows. Report what you ran, what you saw, and any behavior that does not match plan.md. Do not fix anything; report only.
1
+ Start the app with `pnpm dev`, which needs a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`. Exercise the changed behavior and the two nearest neighboring flows. Report what you ran, what you saw, and any behavior that does not match plan.md. Do not fix anything; report only.
@@ -0,0 +1,21 @@
1
+ # Review instructions
2
+
3
+ ## Passes
4
+
5
+ Run three passes and tag each finding with its pass:
6
+
7
+ - Bugs: logic errors, broken edge cases, subtle regressions
8
+ - Security: injection risks, authentication gaps, PII in logs
9
+ - Compliance: the change matches spec.md, plan.md and the design principles that the four policies in `.agents/skills/` state; flag a plan.md that has no `Accepted by:` line and a change that makes `AGENTS.md` outdated
10
+
11
+ ## What Important means here
12
+
13
+ Reserve Important for findings that would break behavior, leak data or breach a policy. Style and naming are nits.
14
+
15
+ ## Cap the nits
16
+
17
+ Report at most five nits per review; summarize the rest as a count.
18
+
19
+ ## Do not report
20
+
21
+ Generated files and anything CI already enforces: `pnpm-lock.yaml`, `src/app/(payload)/**`, `src/migrations/**`, and `src/payload-types.ts`.
@@ -4,4 +4,4 @@ description: Runs the app and checks the change works before the session reports
4
4
  tools: Bash, Read
5
5
  ---
6
6
 
7
- Start the app with `pnpm dev`. Exercise the changed behavior and the two nearest neighboring flows. Report what you ran, what you saw, and any behavior that does not match plan.md. Do not fix anything; report only.
7
+ Start the app with `pnpm dev`, which needs a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`. Exercise the changed behavior and the two nearest neighboring flows. Report what you ran, what you saw, and any behavior that does not match plan.md. Do not fix anything; report only.
@@ -4,4 +4,4 @@ description: Runs the app and checks the change works before the session reports
4
4
  readonly: true
5
5
  ---
6
6
 
7
- Start the app with `pnpm dev`. Exercise the changed behavior and the two nearest neighboring flows. Report what you ran, what you saw, and any behavior that does not match plan.md. Do not fix anything; report only.
7
+ Start the app with `pnpm dev`, which needs a PostgreSQL database in `DATABASE_URL` and `PAYLOAD_SECRET` in `.env`. Exercise the changed behavior and the two nearest neighboring flows. Report what you ran, what you saw, and any behavior that does not match plan.md. Do not fix anything; report only.
@@ -20,8 +20,8 @@
20
20
  }
21
21
  ],
22
22
  "options": {
23
+ "parser": "swc",
23
24
  "skipAnalysisNotInRules": true,
24
- "tsPreCompilationDeps": true,
25
25
  "enhancedResolveOptions": {
26
26
  "conditionNames": ["import", "require", "node", "default", "types"],
27
27
  "exportsFields": ["exports"]
@@ -21,7 +21,7 @@ body:
21
21
  id: version
22
22
  attributes:
23
23
  label: Commit
24
- placeholder: 769e0ef
24
+ placeholder: Output of `git rev-parse --short HEAD`
25
25
  validations:
26
26
  required: true
27
27
  - type: textarea
@@ -90,16 +90,14 @@ jobs:
90
90
  with:
91
91
  cache: true
92
92
  require-lockfile: true
93
- - name: Reject suppression directives
94
- run: pnpm suppressions:check
95
- - name: Check Cursor rules match .agents/rules
93
+ - name: Check rendered agent rules match .agents/rules
96
94
  run: pnpm rules:check
97
95
  - name: Check agent gates
98
96
  run: pnpm gates:check
99
- - name: Check human gates
100
- run: pnpm human-gates:check
101
- - name: Self-test the intent checker
102
- run: pnpm intent:check
97
+ - name: Check plans
98
+ run: pnpm plan:check
99
+ - name: Check bands
100
+ run: pnpm bands:check
103
101
  - name: Check lint
104
102
  run: pnpm lint:check
105
103
  - name: Check formatting
@@ -108,8 +106,6 @@ jobs:
108
106
  GITHUB_TOKEN: ${{ github.token }} # editorconfig-checker downloads its binary from GitHub releases; the token avoids the anonymous rate limit.
109
107
  - name: Check package.json ordering
110
108
  run: pnpm sort-package-json:check
111
- - name: Validate peer dependency contracts
112
- run: pnpm peers:check
113
109
  - name: Check types
114
110
  run: pnpm typecheck
115
111
  - name: Run Knip
@@ -143,7 +139,23 @@ jobs:
143
139
  if: needs.changes.outputs.full_verification == 'true' || github.event_name == 'schedule'
144
140
  runs-on: ubuntu-latest
145
141
  timeout-minutes: 15
142
+ services:
143
+ postgres:
144
+ image: postgres:17.11-alpine@sha256:266d3c257594e195b309ae9d1805e54c788f1d7b375f56bf6c367aac6c917e7b
145
+ env:
146
+ POSTGRES_PASSWORD: postgres
147
+ POSTGRES_DB: payload
148
+ ports:
149
+ - 5432:5432
150
+ options: >-
151
+ --health-cmd "pg_isready --username postgres"
152
+ --health-interval 5s
153
+ --health-timeout 5s
154
+ --health-retries 10
146
155
  env:
156
+ DATABASE_URL: postgres://postgres:postgres@localhost:5432/payload
157
+ PAYLOAD_SECRET: ci-only-secret
158
+ APP_URL: http://localhost:3000
147
159
  HADOLINT_VERSION: 2.15.1
148
160
  HADOLINT_SHA256: c7187db94eeeeca956519a6af171adc31453941a1e777961f6e680f697c8c507
149
161
  TRIVY_VERSION: 0.76.1
@@ -165,7 +177,7 @@ jobs:
165
177
  - name: Smoke test image
166
178
  id: smoke
167
179
  run: |
168
- docker run --detach --name app --env PORT=3000 --publish 3000:3000 app:ci
180
+ docker run --detach --name app --network host --env PORT=3000 --env DATABASE_URL --env PAYLOAD_SECRET --env APP_URL app:ci
169
181
  curl --silent --show-error --fail --retry 15 --retry-delay 1 --retry-all-errors --output /dev/null http://localhost:3000/health
170
182
  - name: Show container logs
171
183
  if: failure() && steps.smoke.outcome == 'failure'
@@ -193,6 +205,59 @@ jobs:
193
205
  environment: dev
194
206
  commit_sha: ${{ github.sha }}
195
207
 
208
+ triage:
209
+ name: Triage failed build
210
+ needs:
211
+ - changes
212
+ - checks
213
+ - image
214
+ if: failure() && vars.CLAUDE_CI_ENABLED == 'true' && github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
215
+ runs-on: ubuntu-latest
216
+ timeout-minutes: 15
217
+ permissions:
218
+ actions: read # Needed to read the logs of the failed jobs.
219
+ id-token: write # Needed to authenticate the Claude GitHub App with the workflow's OIDC token.
220
+ pull-requests: write # Needed to post the summary on the pull request.
221
+ steps:
222
+ - name: Require a Claude credential
223
+ env:
224
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
225
+ CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
226
+ run: |
227
+ [[ -n "$ANTHROPIC_API_KEY" || -n "$CLAUDE_CODE_OAUTH_TOKEN" ]] || { echo "::error::Set the CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY repository secret"; exit 1; }
228
+ - name: Collect the build log
229
+ env:
230
+ GH_TOKEN: ${{ github.token }}
231
+ REPOSITORY: ${{ github.repository }}
232
+ RUN_ID: ${{ github.run_id }}
233
+ run: |
234
+ mkdir -p out
235
+ for job in $(gh api "repos/$REPOSITORY/actions/runs/$RUN_ID/jobs" --paginate --jq '.jobs[] | select(.conclusion == "failure") | .id'); do
236
+ gh api --allow-escape-sequences "repos/$REPOSITORY/actions/jobs/$job/logs" >> out/build.log
237
+ done
238
+ - name: Triage failed build
239
+ id: triage
240
+ uses: anthropics/claude-code-action@61a9c274fa7110a66dfafc1bbbced03833eb25fe # v1.0.269
241
+ with:
242
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
243
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
244
+ prompt: >
245
+ Read the build log at out/build.log. Identify the most
246
+ likely cause, say whether the failure looks flaky or real, and write a
247
+ three-line summary for the PR thread.
248
+ claude_args: >-
249
+ --model claude-haiku-5-5
250
+ --max-turns 5
251
+ --allowedTools "Read"
252
+ --json-schema '{"type":"object","properties":{"summary":{"type":"string"}},"required":["summary"]}'
253
+ - name: Post the summary
254
+ env:
255
+ GH_TOKEN: ${{ github.token }}
256
+ PR_NUMBER: ${{ github.event.pull_request.number }}
257
+ REPOSITORY: ${{ github.repository }}
258
+ SUMMARY: ${{ fromJSON(steps.triage.outputs.structured_output).summary }}
259
+ run: gh pr comment "$PR_NUMBER" --repo "$REPOSITORY" --body "$SUMMARY"
260
+
196
261
  ci:
197
262
  name: All Checks
198
263
  if: always()
@@ -5,11 +5,6 @@ on:
5
5
  push:
6
6
  branches:
7
7
  - main
8
- paths-ignore:
9
- - "**/*.md"
10
- - ".agents/**"
11
- - ".claude/**"
12
- - ".cursor/**"
13
8
  schedule:
14
9
  - cron: "17 2 * * 1"
15
10
 
@@ -4,49 +4,53 @@ Payload CMS on Next.js App Router and PostgreSQL, in TypeScript on pnpm and Node
4
4
 
5
5
  ## Commands
6
6
 
7
- | Task | Command |
8
- | :---------------------------- | :--------------------------------------------------------- |
9
- | Start with reload | `pnpm dev` |
10
- | One test | `pnpm vitest run src/environment.test.ts -t "<test name>"` |
11
- | Unit tests | `pnpm test`, or `pnpm test:coverage` |
12
- | End-to-end tests | `pnpm test:e2e` |
13
- | Regenerate after a collection | `pnpm generate:types`, `pnpm generate:importmap` |
14
- | Create a migration | `pnpm migrate:create <name>` |
15
- | What `pre-push` runs | `pnpm check` |
16
- | Every check | `pnpm verify` |
17
- | Render rules after a change | `pnpm rules:sync` |
7
+ | Task | Command | Healthy output |
8
+ | :--------------------------------- | :--------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------- |
9
+ | Start with reload | `pnpm dev` | `✓ Ready in 251ms` |
10
+ | One test | `pnpm vitest run src/environment.test.ts -t "<test name>"` | `Tests 1 passed \| 2 skipped (3)` |
11
+ | Unit tests | `pnpm test`, or `pnpm test:coverage` | `Tests 13 passed (13)` |
12
+ | End-to-end tests | `pnpm test:e2e` | `2 passed (9.4s)`, with `DATABASE_URL` pointing at a running database |
13
+ | Regenerate after a collection | `pnpm generate:types`, `pnpm generate:importmap` | `INFO: Compiling TS types for Collections and Globals...`, then nothing; `No new imports found, skipping writing import map` |
14
+ | Create a migration | `pnpm migrate:create <name>` | `INFO: Migration created at` the new file under `migrations/`, then `INFO: Done.` |
15
+ | What `pre-push` runs | `pnpm check` | exits 0; the last output is the route table of `next build` with `ƒ /health` |
16
+ | Every check except `pnpm test:e2e` | `pnpm verify` | exits 0; the last output is the route table of `next build` with `ƒ /health` |
17
+ | Render rules after a change | `pnpm rules:sync` | `Synced 69 agent rule files; 0 updated.` |
18
18
 
19
19
  ## Verifying your work
20
20
 
21
21
  - Build: `pnpm build` (prints the `Route (app)` table)
22
22
  - Test: `pnpm test:coverage` (all green, then the coverage summary; never skip or delete a failing test)
23
- - Lint: `pnpm verify:static` (ESLint allows zero warnings; prints `✔ no dependency violations found`)
23
+ - Static checks: `pnpm verify:static` (ESLint allows zero warnings; every check must pass)
24
24
 
25
25
  Run all three before reporting any task complete, and paste the output. `pnpm verify` runs all three.
26
26
 
27
27
  ## Architecture
28
28
 
29
- - `src/payload.config.ts` wires the collections in `src/collections/` to PostgreSQL. The site lives in `src/app/(frontend)/`, and `src/app/health/route.ts` serves `/health`.
30
- - In development, Payload applies collection changes to the database directly. In production, the server applies the migrations in `src/migrations/` when it starts.
29
+ - `src/payload.config.ts` wires the collections in `src/collections/` to PostgreSQL. The site lives in `src/app/(frontend)/`, and `src/app/health/route.ts` serves `/health`. `next.config.ts` builds `output: "standalone"` and leaves Cache Components off.
30
+ - In development, Payload applies collection changes to the database directly. In production, Payload applies the migrations in `src/migrations/` when it first initialises, which `/health` triggers, so the first health check after a deploy applies them, not when the server starts.
31
31
 
32
32
  ## Conventions
33
33
 
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.
34
+ 1. **Change the schema only through collections, then regenerate and commit.** Payload generates `src/payload-types.ts`, `src/migrations/`, and `src/app/(payload)/admin/importMap.ts`; run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>`. Do not edit those files by hand.
35
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
36
  3. **Component tests need a DOM test environment, and Vitest runs in Node.js.** Add that environment with the first component test.
37
37
  4. **Read configuration through `requireEnvironment` in `src/environment.ts`.** Document each variable in `.env.example`.
38
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`.
39
+ 6. **Start a bug fix with a failing test.** A bug fix has no intent and no spec; its plan, `intent/<short-description>/plan.md`, is accepted by an engineer before any code changes. Reproduce the bug as a test, confirm it fails for the reason you expect, and commit it on a `fix/` branch. Then `.agents/hooks/agent-test-edit-gate.sh` blocks test edits by itself: make the test pass without editing it. On a branch with another name, create `.git/bug-fix-in-progress` first, and delete it once the test passes.
40
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
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.
42
+ 9. **Write replies a person can check.** 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.
43
+ 10. **Run parallel sessions in separate worktrees, on tasks that touch different files.** Start each with `claude --worktree <name>`: a worktree is its own checkout on its own branch. Tasks that share files run in one session, one after another. Start with two or three sessions, and add one only while you can review every stream properly.
43
44
 
44
45
  ## Things Claude gets wrong
45
46
 
46
47
  When Claude makes a mistake twice, add the correction here.
47
48
 
48
49
  - **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`.
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.
50
+ - **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. Any value lifts the gate except an empty value, `0`, `false`, and `no`, in any letter case. 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
+ - **Issues**: open an issue only to hand work to another person, never to give a pull request a number to close. A pull request closes an issue that already exists with `Closes #<issue>`.
52
+ - **What belongs in the repository**: files, commit messages, and pull requests hold the change, its reason, and the checks. Write no date, log, history, mistake count, token figure, or session note into a file.
53
+ - **Sourced requirements**: add a requirement to an intent, spec, or plan only when a person decided it or a named source says it. This includes a requirement a review bot suggests. When no person decided it and no source says it, leave it out and answer the thread with that.
50
54
 
51
55
  <!-- BEGIN:nextjs-agent-rules -->
52
56
 
@@ -8,7 +8,7 @@ Use this guide to prepare changes to this repository.
8
8
  - Change the Node.js version in `.nvmrc` and the `Dockerfile` together. Dependabot updates only the `Dockerfile`.
9
9
  - Install pnpm once with `npm install --global pnpm`. It switches to the version declared by `package.json#packageManager` automatically.
10
10
  - Use Claude Code v2.1.295 or later. It reads `CLAUDE.md`, which imports `AGENTS.md`, and supports the `onFailure` field the agent hooks use.
11
- - Install gitleaks 8.19 or later, which the `pre-commit` hook runs, and jq, which the agent hooks and the `pre-push` hook (`pnpm gates:check`) need: `brew install gitleaks jq` on macOS, or install them from each project's releases on Linux.
11
+ - Install gitleaks 8.21 or later, which the `pre-commit` hook runs, and jq, which the agent hooks and the `pre-push` hook (`pnpm gates:check`) need: `brew install gitleaks jq` on macOS, or install them from each project's releases on Linux.
12
12
 
13
13
  From the repository root:
14
14
 
@@ -21,7 +21,7 @@ pnpm install
21
21
 
22
22
  - Fix lint, type, and test failures at their root cause.
23
23
  - Put unit tests next to the code as `*.test.ts` and Playwright end-to-end tests in `test/` as `*.e2e.test.ts`.
24
- - Change the database schema only through collections, then run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>` and commit the generated files. Production applies pending migrations when the server starts.
24
+ - Change the database schema only through collections, then run `pnpm generate:types`, `pnpm generate:importmap`, and `pnpm migrate:create <name>` and commit the generated files. Production applies pending migrations when Payload first initialises, which `/health` triggers.
25
25
  - Treat `coverage/` as generated output.
26
26
  - Do not commit `.env` files or credentials.
27
27
 
@@ -36,9 +36,10 @@ Run the narrowest check that covers the change while you work. Git hooks run the
36
36
  | `pre-merge-commit` | blocks merge commits on `main` |
37
37
  | `pre-push` | blocks pushes to `main` except the push that creates it, then `pnpm check`: the static checks, the unit tests related to your changes, and the production build |
38
38
 
39
- - **Scans:** CI also runs coverage, the build, the container image, and the secret, SAST, OSV, CodeQL, dependency-review, and OpenSSF Scorecard scans. Dependabot and OSV-Scanner report vulnerable dependencies.
39
+ - **Scans:** CI also runs coverage, the build, the container image, and the secret, SAST, OSV, CodeQL, dependency-review, and OpenSSF Scorecard scans. CodeQL, dependency-review, and Scorecard run on public repositories, and on private ones when the `CODE_SCANNING` repository variable is `true`. Dependabot and OSV-Scanner report vulnerable dependencies.
40
40
  - **End-to-end tests:** run `pnpm test:e2e` when you change pages or the admin panel. It starts the development server unless one is already running, and needs `DATABASE_URL` and `PAYLOAD_SECRET` from `.env`. Run `pnpm exec playwright install chromium` once before the first run. CI runs it against the production build and a PostgreSQL service on every pull request that is ready for review and changes code.
41
41
  - **Coverage:** CI requires 95% branch coverage on changed lines in `src/`, except layouts, the Payload config, and generated files.
42
+ - **Agent evals:** run `pnpm evals:run` after you change `AGENTS.md`, a skill under `.agents/skills/`, or a hook under `.agents/hooks/`, and add a case name to run one case. It runs the cases in `.agents/skill-evals/` with Claude Code on your own Claude login, so it spends your Claude usage, and it is not part of `pnpm verify`.
42
43
 
43
44
  Run `pnpm verify` for repository changes.
44
45
 
@@ -1,6 +1,6 @@
1
1
  # Runs on any OCI platform (Railway, Fly.io, Cloud Run). On Vercel, deploy without it. The platform sets `PORT`.
2
2
  FROM \
3
- node@sha256:06d7adf3e0ef61a13f1d28682726366f97a15aa1888c934d3ecec86c33918b53 \
3
+ node:24.22.1-alpine@sha256:06d7adf3e0ef61a13f1d28682726366f97a15aa1888c934d3ecec86c33918b53 \
4
4
  AS build
5
5
  ENV NEXT_TELEMETRY_DISABLED=1
6
6
  WORKDIR /app
@@ -14,7 +14,7 @@ COPY src ./src
14
14
  RUN PAYLOAD_SECRET=build-only DATABASE_URL=postgres://build-only@localhost/build-only APP_URL=http://localhost:3000 pnpm build
15
15
 
16
16
  FROM \
17
- node@sha256:06d7adf3e0ef61a13f1d28682726366f97a15aa1888c934d3ecec86c33918b53
17
+ node:24.22.1-alpine@sha256:06d7adf3e0ef61a13f1d28682726366f97a15aa1888c934d3ecec86c33918b53
18
18
  ENV NODE_ENV=production NEXT_TELEMETRY_DISABLED=1 HOSTNAME=0.0.0.0
19
19
  WORKDIR /app
20
20
  # Apply Alpine security fixes released after the base image, and drop npm, corepack, and yarn: the app never runs them, and their bundled dependencies carry their own CVEs.
@@ -1,6 +1,6 @@
1
1
  # next-friday-template-payload
2
2
 
3
- Next Friday starter for Payload CMS on Next.js and PostgreSQL. The API is REST at `/api`.
3
+ Payload CMS application on Next.js and PostgreSQL. The API is REST at `/api`.
4
4
 
5
5
  ## Getting started
6
6
 
@@ -20,11 +20,11 @@ Then open `http://localhost:3000/admin` to create the first user.
20
20
 
21
21
  **Warning:** until the first user exists, anyone who can reach `/admin` can create it. Create the first user in each deployed environment right after its first deploy, before you share the URL.
22
22
 
23
- In development, Payload applies collection changes to the database directly. In production, the server applies the migrations in `src/migrations/` when it starts.
23
+ In development, Payload applies collection changes to the database directly. In production, Payload applies the migrations in `src/migrations/` when it first initialises, which `/health` triggers, so the first health check after a deploy applies them and fails while the database is unreachable.
24
24
 
25
25
  ## After creating a project from this template
26
26
 
27
- Follow [SETUP.md](SETUP.md) in order. It sets up the repository, the reviews, and the AI-native SDLC. In step 1, also replace the `Next Friday Payload template` text in `src/app/(frontend)/layout.tsx`, `src/app/(frontend)/page.tsx`, and their tests.
27
+ Follow [SETUP.md](SETUP.md) in order. It sets up the repository, the reviews, and the AI-native SDLC. In step 1, also replace the `Payload application` text in `src/app/(frontend)/layout.tsx`, `src/app/(frontend)/page.tsx`, and `src/app/(frontend)/page.test.ts`.
28
28
 
29
29
  ## Scripts
30
30
 
@@ -42,7 +42,9 @@ Follow [SETUP.md](SETUP.md) in order. It sets up the repository, the reviews, an
42
42
  | `pnpm check` | Run the static checks, the unit tests for changed code, and the production build (the `pre-push` hook) |
43
43
  | `pnpm verify` | Run the static checks, all unit tests with coverage, and the production build |
44
44
 
45
- CI also runs the build, the end-to-end tests, the container image scan, and the security scans, including CodeQL, dependency review, and OpenSSF Scorecard. CodeQL and Scorecard run on public repositories, and on private ones when the `CODE_SCANNING` repository variable is `true`.
45
+ `pnpm build` copies `.env` into `.next/standalone`, where every secret sits in plain text. Keep that folder out of images and archives.
46
+
47
+ CI also runs the build, the end-to-end tests, the container image scan, and the security scans, including CodeQL, dependency review, and OpenSSF Scorecard. CodeQL, dependency review, and Scorecard run on public repositories, and on private ones when the `CODE_SCANNING` repository variable is `true`.
46
48
 
47
49
  ## Container
48
50
 
@@ -55,6 +57,8 @@ docker run --publish 3000:3000 --env DATABASE_URL --env PAYLOAD_SECRET --env APP
55
57
 
56
58
  Uploaded images, up to 10 MB each, are written to the container filesystem, which a redeploy discards. Add a Payload storage adapter, for example `@payloadcms/storage-s3`, before storing media in production.
57
59
 
60
+ The config sets no `email` adapter, so Payload writes every email, including password-reset links, to the server log. Set `email` in `src/payload.config.ts` before production.
61
+
58
62
  On Vercel, deploy without the image; the Next.js preset takes precedence over the `Dockerfile`.
59
63
 
60
64
  ## Deploy
@@ -0,0 +1,21 @@
1
+ # Review instructions
2
+
3
+ ## Passes
4
+
5
+ Run three passes and tag each finding with its pass:
6
+
7
+ - Bugs: logic errors, broken edge cases, subtle regressions
8
+ - Security: injection risks, authentication gaps, PII in logs
9
+ - Compliance: the change matches spec.md, plan.md and the design principles that the four policies in `.agents/skills/` state; flag a plan.md that has no `Accepted by:` line and a change that makes `AGENTS.md` outdated
10
+
11
+ ## What Important means here
12
+
13
+ Reserve Important for findings that would break behavior, leak data or breach a policy. Style and naming are nits.
14
+
15
+ ## Cap the nits
16
+
17
+ Report at most five nits per review; summarize the rest as a count.
18
+
19
+ ## Do not report
20
+
21
+ Generated files and anything CI already enforces: `pnpm-lock.yaml`, `src/app/(payload)/**`, `src/migrations/**`, and `src/payload-types.ts`.