@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
@@ -0,0 +1,115 @@
1
+ name: Control band
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 6 * * *"
6
+
7
+ permissions: {}
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}
11
+ cancel-in-progress: false
12
+
13
+ jobs:
14
+ detect:
15
+ name: Detect the tier
16
+ if: vars.CLAUDE_CI_ENABLED == 'true'
17
+ runs-on: ubuntu-latest
18
+ timeout-minutes: 15
19
+ permissions:
20
+ actions: read # Needed by a metric command that reads workflow runs.
21
+ contents: read
22
+ outputs:
23
+ action: ${{ steps.tier.outputs.action }}
24
+ report: ${{ steps.tier.outputs.report }}
25
+ routes: ${{ steps.tier.outputs.routes }}
26
+ tools: ${{ steps.tier.outputs.tools }}
27
+ values: ${{ steps.tier.outputs.values }}
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
31
+ with:
32
+ persist-credentials: false
33
+ - name: Set up Node.js and pnpm
34
+ uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0
35
+ with:
36
+ cache: true
37
+ require-lockfile: true
38
+ - name: Measure the metric
39
+ env:
40
+ GH_TOKEN: ${{ github.token }}
41
+ METRIC_COMMAND: ${{ vars.CONTROL_BAND_METRIC_COMMAND }}
42
+ run: |
43
+ [[ -n "$METRIC_COMMAND" ]] || { echo "::error::Set the CONTROL_BAND_METRIC_COMMAND repository variable to a command that writes metric-values.json"; exit 1; }
44
+ bash -euo pipefail -c "$METRIC_COMMAND"
45
+ [[ -f metric-values.json ]] || { echo "::error::CONTROL_BAND_METRIC_COMMAND did not write metric-values.json"; exit 1; }
46
+ - name: Detect the tier
47
+ id: tier
48
+ run: |
49
+ report="$(pnpm --silent bands:check metric-values.json)"
50
+ {
51
+ echo "report=$report"
52
+ echo "action=$(jq --raw-output '.action // "none"' <<< "$report")"
53
+ echo "routes=$(jq --compact-output '.routes // []' <<< "$report")"
54
+ echo "tools=$(jq --raw-output '.tools // ""' <<< "$report")"
55
+ echo "values=$(jq --compact-output . metric-values.json)"
56
+ } >> "$GITHUB_OUTPUT"
57
+
58
+ respond:
59
+ name: Respond to the finding
60
+ needs: detect
61
+ if: vars.CLAUDE_CI_ENABLED == 'true' && (needs.detect.outputs.action == 'diagnose' || needs.detect.outputs.action == 'propose')
62
+ runs-on: ubuntu-latest
63
+ timeout-minutes: 20
64
+ permissions:
65
+ actions: read # Needed by the tier's tools that read workflow runs.
66
+ contents: write # Needed to push the intent branch; the agent has no route to push main.
67
+ id-token: write # Needed to authenticate the Claude GitHub App with the workflow's OIDC token.
68
+ pull-requests: write # Needed to open the intent pull request.
69
+ steps:
70
+ - name: Require a Claude credential
71
+ env:
72
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
73
+ CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
74
+ run: |
75
+ [[ -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; }
76
+ - name: Checkout repository
77
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
78
+ with:
79
+ fetch-depth: 0
80
+ persist-credentials: false
81
+ - name: Create the intent branch
82
+ if: contains(fromJSON(needs.detect.outputs.routes), 'pull_request')
83
+ run: git switch --create "docs/band-finding-$GITHUB_RUN_ID"
84
+ - name: Diagnose
85
+ if: ${{ !contains(fromJSON(needs.detect.outputs.routes), 'pull_request') }}
86
+ uses: anthropics/claude-code-action@61a9c274fa7110a66dfafc1bbbced03833eb25fe # v1.0.269
87
+ with:
88
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
89
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
90
+ prompt: |
91
+ /sdlc A scheduled job found a control band deviation in production. No one can answer questions.
92
+ Detection report: ${{ needs.detect.outputs.report }}
93
+ Metric values, oldest first: ${{ needs.detect.outputs.values }}
94
+ The values come from the command in the CONTROL_BAND_METRIC_COMMAND repository variable. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
95
+ claude_args: |
96
+ --model claude-haiku-5-5
97
+ --max-turns 15
98
+ --allowedTools "${{ needs.detect.outputs.tools || 'Read,Grep,Glob' }}"
99
+ - name: Write the intent
100
+ if: contains(fromJSON(needs.detect.outputs.routes), 'pull_request')
101
+ uses: anthropics/claude-code-action@61a9c274fa7110a66dfafc1bbbced03833eb25fe # v1.0.269
102
+ with:
103
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
104
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
105
+ prompt: |
106
+ /sdlc A scheduled job found a control band deviation in production. No one can answer questions.
107
+ Detection report: ${{ needs.detect.outputs.report }}
108
+ Metric values, oldest first: ${{ needs.detect.outputs.values }}
109
+ The values come from the command in the CONTROL_BAND_METRIC_COMMAND repository variable. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
110
+ The branch docs/band-finding-${{ github.run_id }} exists and is checked out. Commit intent.md on it, push it with git push --set-upstream origin docs/band-finding-${{ github.run_id }}, open the pull request, and stop at the service owner's gate. A route other than pull_request is a runbook: name its command in the intent and do not run it.
111
+ claude_args: |
112
+ --model claude-haiku-5-5
113
+ --max-turns 25
114
+ --permission-mode acceptEdits
115
+ --allowedTools "${{ needs.detect.outputs.tools || 'Read,Grep,Glob' }},Write,Edit,Bash(git add *),Bash(git commit *),Bash(git status *),Bash(git log *),Bash(git push --set-upstream origin docs/band-finding-${{ github.run_id }}),Bash(gh pr create *)"
@@ -12,6 +12,7 @@ concurrency:
12
12
  jobs:
13
13
  dependency-review:
14
14
  name: Dependency Review
15
+ if: github.event.repository.visibility == 'public' || vars.CODE_SCANNING == 'true'
15
16
  runs-on: ubuntu-latest
16
17
  timeout-minutes: 10
17
18
  permissions:
@@ -51,6 +51,7 @@ jobs:
51
51
  persist-credentials: false
52
52
  - name: Require the commit on main with passing CI and a deployment to the previous environment
53
53
  if: github.event_name == 'workflow_dispatch'
54
+ shell: bash
54
55
  env:
55
56
  GH_TOKEN: ${{ github.token }}
56
57
  REPOSITORY: ${{ github.repository }}
@@ -116,11 +117,12 @@ jobs:
116
117
  run: railway up --ci --service "$RAILWAY_SERVICE" --environment "$RAILWAY_ENVIRONMENT"
117
118
  - name: Require a healthy deployment
118
119
  run: |
120
+ health_url="${APP_URL%/}/health"
119
121
  for _ in $(seq 30); do
120
- if curl --silent --fail --output /dev/null "$APP_URL/health"; then
122
+ if curl --silent --fail --output /dev/null "$health_url"; then
121
123
  exit 0
122
124
  fi
123
125
  sleep 10
124
126
  done
125
- echo "::error::$APP_URL/health did not respond"
127
+ echo "::error::$health_url did not respond"
126
128
  exit 1
@@ -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: "37 2 * * 1"
15
10
 
@@ -1,4 +1,4 @@
1
- name: PR Labeler
1
+ name: PR Triage
2
2
 
3
3
  on:
4
4
  pull_request_target:
@@ -43,8 +43,11 @@ jobs:
43
43
  tar --extract --gzip --file "$archive" gitleaks
44
44
  - name: Scan history with repository rules
45
45
  run: |
46
+ config=.gitleaks.toml
46
47
  log_opts=()
47
48
  if [[ -n "$PR_BASE_SHA" ]]; then
49
+ config="$RUNNER_TEMP/gitleaks.toml"
50
+ git show "${PR_BASE_SHA}:.gitleaks.toml" > "$config"
48
51
  log_opts=(--log-opts="${PR_BASE_SHA}..${PR_HEAD_SHA}")
49
52
  fi
50
- ./gitleaks git --redact --config .gitleaks.toml --no-banner "${log_opts[@]}" .
53
+ ./gitleaks git --redact --config "$config" --no-banner "${log_opts[@]}" .
@@ -0,0 +1,108 @@
1
+ name: Spec on intent merge
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - intent/*/intent.md
9
+
10
+ permissions: {}
11
+
12
+ concurrency:
13
+ group: ${{ github.workflow }}
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ find:
18
+ name: Find merged intents
19
+ if: vars.CLAUDE_CI_ENABLED == 'true'
20
+ runs-on: ubuntu-latest
21
+ timeout-minutes: 5
22
+ permissions:
23
+ contents: read
24
+ outputs:
25
+ intents: ${{ steps.find.outputs.intents }}
26
+ steps:
27
+ - name: Checkout repository
28
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
29
+ with:
30
+ fetch-depth: 0
31
+ persist-credentials: false
32
+ - name: List merged intents without a spec
33
+ id: find
34
+ env:
35
+ BEFORE: ${{ github.event.before }}
36
+ AFTER: ${{ github.sha }}
37
+ run: |
38
+ if [[ "$BEFORE" =~ ^0+$ ]]; then
39
+ changed="$(git ls-tree -r --name-only "$AFTER")"
40
+ else
41
+ changed="$(git diff --name-only --diff-filter=AM "$BEFORE" "$AFTER")"
42
+ fi
43
+ : > intents.txt
44
+ while IFS= read -r path; do
45
+ [[ "$path" =~ ^intent/[A-Za-z0-9._-]+/intent\.md$ ]] || continue
46
+ grep --extended-regexp --quiet 'Status: (draft|accepted)\.$' "$path" || continue
47
+ [[ ! -e "$(dirname "$path")/spec.md" ]] || continue
48
+ echo "$path" >> intents.txt
49
+ done <<< "$changed"
50
+ echo "intents=$(jq --raw-input --null-input --compact-output '[inputs]' < intents.txt)" >> "$GITHUB_OUTPUT"
51
+
52
+ spec:
53
+ name: Write the spec for ${{ matrix.intent }}
54
+ needs: find
55
+ if: vars.CLAUDE_CI_ENABLED == 'true' && needs.find.outputs.intents != '[]'
56
+ runs-on: ubuntu-latest
57
+ timeout-minutes: 20
58
+ permissions:
59
+ contents: write # Needed to push the spec branch; the agent has no route to push main.
60
+ id-token: write # Needed to authenticate the Claude GitHub App with the workflow's OIDC token.
61
+ pull-requests: write # Needed to open the pull request.
62
+ strategy:
63
+ fail-fast: false
64
+ max-parallel: 1
65
+ matrix:
66
+ intent: ${{ fromJSON(needs.find.outputs.intents) }}
67
+ env:
68
+ INTENT: ${{ matrix.intent }}
69
+ steps:
70
+ - name: Require a Claude credential
71
+ env:
72
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
73
+ CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
74
+ run: |
75
+ [[ -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; }
76
+ - name: Checkout repository
77
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
78
+ with:
79
+ fetch-depth: 0
80
+ persist-credentials: false
81
+ - name: Create the spec branch
82
+ id: branch
83
+ run: |
84
+ change="${INTENT#intent/}"
85
+ change="${change%/intent.md}"
86
+ git switch --create "docs/spec-$change"
87
+ echo "name=docs/spec-$change" >> "$GITHUB_OUTPUT"
88
+ - name: Write the spec
89
+ uses: anthropics/claude-code-action@61a9c274fa7110a66dfafc1bbbced03833eb25fe # v1.0.269
90
+ with:
91
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
92
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
93
+ prompt: |
94
+ /sdlc ${{ matrix.intent }}
95
+ The branch ${{ steps.branch.outputs.name }} exists and is checked out. Commit spec.md on it, push it with git push --set-upstream origin ${{ steps.branch.outputs.name }}, open the pull request, and stop at the product owner's gate.
96
+ claude_args: |
97
+ --model claude-haiku-5-5
98
+ --max-turns 30
99
+ --permission-mode acceptEdits
100
+ --allowedTools "Read,Write,Edit,Glob,Grep,Bash(git add *),Bash(git commit *),Bash(git status *),Bash(git log *),Bash(git push --set-upstream origin ${{ steps.branch.outputs.name }}),Bash(gh pr create *)"
101
+ - name: Require the pull request
102
+ env:
103
+ BRANCH: ${{ steps.branch.outputs.name }}
104
+ GH_TOKEN: ${{ github.token }}
105
+ REPOSITORY: ${{ github.repository }}
106
+ run: |
107
+ count="$(gh pr list --repo "$REPOSITORY" --head "$BRANCH" --state open --json number --jq length)"
108
+ [[ "$count" -gt 0 ]] || { echo "::error::No pull request was opened from $BRANCH"; exit 1; }
@@ -8,8 +8,7 @@ on:
8
8
  - reopened
9
9
  - synchronize
10
10
 
11
- permissions:
12
- pull-requests: read # Needed to read the pull request title for semantic validation.
11
+ permissions: {}
13
12
 
14
13
  concurrency:
15
14
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
@@ -21,6 +20,8 @@ jobs:
21
20
  if: github.event.pull_request.user.login != 'dependabot[bot]'
22
21
  runs-on: ubuntu-latest
23
22
  timeout-minutes: 10
23
+ permissions:
24
+ pull-requests: read # Needed to read the pull request title for semantic validation.
24
25
  steps:
25
26
  - name: Validate pull request title
26
27
  uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
@@ -2,18 +2,11 @@
2
2
  set -e
3
3
 
4
4
  # The first push of a new repository creates main on the remote, so it is the only push allowed there.
5
- while read -r local_ref _ remote_ref remote_oid; do
5
+ while read -r _ _ remote_ref remote_oid; do
6
6
  if [ "$remote_ref" = refs/heads/main ] && [ -n "$(printf '%s' "$remote_oid" | tr -d 0)" ]; then
7
7
  echo "pre-push: do not push to main. Push your branch and open a pull request." >&2
8
8
  exit 1
9
9
  fi
10
- branch="${remote_ref#refs/heads/}"
11
- if [ "$branch" != "$remote_ref" ] && [ -z "$(printf '%s' "$remote_oid" | tr -d 0)" ] \
12
- && { git rev-parse --verify --quiet "refs/remotes/$1/$branch" > /dev/null \
13
- || [ "$(git config "branch.${local_ref#refs/heads/}.merge" || true)" = "$remote_ref" ]; }; then
14
- echo "pre-push: $branch no longer exists on $1. Push the work to a new branch from the latest $1/main and open a pull request. To reuse the name, run git fetch --prune and git branch --unset-upstream first." >&2
15
- exit 1
16
- fi
17
10
  done
18
11
 
19
12
  pnpm check || {
@@ -6,7 +6,7 @@ Run three passes and tag each finding with its pass:
6
6
 
7
7
  - Bugs: logic errors, broken edge cases, subtle regressions
8
8
  - Security: injection risks, authentication gaps, PII in logs
9
- - Compliance: the change matches spec.md, plan.md and our design principles; flag a plan.md that has no `Accepted by:` line
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
10
 
11
11
  ## What Important means here
12
12
 
@@ -18,4 +18,4 @@ Report at most five nits per review; summarize the rest as a count.
18
18
 
19
19
  ## Do not report
20
20
 
21
- Generated files under src/gen/ and anything CI already enforces.
21
+ Generated files, such as `pnpm-lock.yaml`, and anything CI already enforces.
@@ -4,7 +4,7 @@ This project runs an AI-native software development loop in Claude Code and Curs
4
4
 
5
5
  ## How a change flows
6
6
 
7
- Send a request with `/sdlc`. `intent/README.md` and the playbooks in `.agents/skills/sdlc/playbooks/` say who acts and who decides at each stage.
7
+ Send a request with `/sdlc`. Only a person starts it; nothing routes work into it by itself. `.agents/skills/sdlc-help/SKILL.md` says how to keep `/sdlc` on for a session in Claude Code and Cursor. `intent/README.md` and the playbooks in `.agents/skills/sdlc/playbooks/` say who acts and who decides at each stage.
8
8
 
9
9
  ## 1. First commit and push
10
10
 
@@ -12,7 +12,7 @@ Send a request with `/sdlc`. `intent/README.md` and the playbooks in `.agents/sk
12
12
 
13
13
  1. Install gitleaks and jq (see [CONTRIBUTING.md](CONTRIBUTING.md)).
14
14
  2. Replace the template's description and owner: `package.json#description`, `repository.url`, and `author`, and any template text that `README.md` → **After creating a project from this template** lists. Change `license` from `UNLICENSED` if the project is open source.
15
- 3. Create an empty repository on GitHub. Make the first commit on `main` and push it there. The Git hooks allow only this first commit and push on `main`; work on branches after that.
15
+ 3. Create an empty repository on GitHub. If the project is not a Git repository yet, run `git init --initial-branch=main`. Make the first commit on `main` and push it there. The Git hooks allow only this first commit and push on `main`; work on branches after that.
16
16
 
17
17
  ```sh
18
18
  git add --all
@@ -39,7 +39,7 @@ In `.github/CODEOWNERS`, add these lines in this order. GitHub uses the last mat
39
39
  /.agents/skills/ux-policy/ @the-ux-policy-owner
40
40
  ```
41
41
 
42
- Also replace the owner placeholder in `.github/zizmor.yml`.
42
+ Replace every owner above with a GitHub user or team that has write access to the repository. Also replace the owner placeholder in `.github/zizmor.yml`.
43
43
 
44
44
  Replace `security@example.com` in `SECURITY.md` with the contact the security policy owner names, such as the security email of the company or of the client.
45
45
 
@@ -60,6 +60,7 @@ Replace `security@example.com` in `SECURITY.md` with the contact the security po
60
60
 
61
61
  Rulesets in a private repository need GitHub Pro, Team, or Enterprise; on GitHub Free, make the repository public or upgrade.
62
62
 
63
+ - **Secrets and variables → Actions → Variables:** in a private repository, set `CODE_SCANNING` to `true` to run CodeQL, Scorecard, and Dependency Review, which need GitHub Code Security there; public repositories run them without it. Set `DEPLOY_ENABLED` to `true` when each push to `main` that passes CI should deploy to `dev`; the README's deploy section sets up the environments.
63
64
  - Create the `needs triage` label, which the issue forms apply: `gh label create "needs triage"`.
64
65
 
65
66
  **Check:** a test pull request shows the two required checks and asks for a code owner's review.
@@ -68,7 +69,7 @@ Replace `security@example.com` in `SECURITY.md` with the contact the security po
68
69
 
69
70
  **Who:** an Owner of the Claude organization, with an owner of the GitHub organization.
70
71
 
71
- - **Code Review:** in [**Admin settings → Claude Code**](https://claude.ai/admin-settings/claude-code#code-review), turn on **Allow code review**, install the Claude GitHub App, and add this repository ([set up Code Review](https://code.claude.com/docs/en/code-review-setup)). It needs a Team or Enterprise plan ([availability](https://code.claude.com/docs/en/code-review#availability)). Keep **Review runs** at **After every push**, the default, so every push to a pull request gets a review. Reviews run on Anthropic's infrastructure, so the repository has no review workflow.
72
+ - **Code Review:** in [**Admin settings → Claude Code**](https://claude.ai/admin-settings/claude-code#code-review), turn on **Allow code review**, install the Claude GitHub App, and add this repository ([set up Code Review](https://code.claude.com/docs/en/code-review-setup)). It needs a Team or Enterprise plan ([availability](https://code.claude.com/docs/en/code-review#availability)). Keep **Review runs** at **After every push**, the default, so every push to a pull request gets a review. Reviews run on Anthropic's infrastructure, so the repository has no review workflow. Anyone with write access can also comment `@claude review` on a pull request to start a review ([comment commands](https://code.claude.com/docs/en/code-review-pull-requests#comment-commands)).
72
73
  - **Managed settings:** deploy the non-negotiable settings and hooks as [managed settings](https://code.claude.com/docs/en/settings), tailored from the example in `.claude/managed-settings.example.json`. Engineers cannot override them.
73
74
  - **Monitoring:** turn on the [OpenTelemetry export](https://code.claude.com/docs/en/monitoring-usage).
74
75
 
@@ -90,12 +91,47 @@ Replace `security@example.com` in `SECURITY.md` with the contact the security po
90
91
  - **Sources of truth (engineering lead):** for each artifact, name one system as the source of truth: this repository, an existing tool such as Jira, or, as the minimum, a link both ways (the record id in the file and the commit SHA in the record).
91
92
  - **Higher risk (engineering lead):** decide which changes count as higher risk. A tech lead or architect approves their specs and plans.
92
93
  - **Policies (each policy owner, with an engineer):** each `.agents/skills/<area>-policy/SKILL.md` ships a default (security: OWASP ASVS 5.0.0 Level 1; UX: WCAG 2.2 Level AA; compliance: the OECD privacy principles; brand: one declared source for every brand value). Review it, replace or add the organization's own rules, then run `pnpm rules:sync`. Test that the skill triggers: ask for the relevant task in different ways and confirm the skill loads each time. The policy owner approves every later change as its code owner.
93
- - **Production gate (engineering leadership, with change management and compliance):** name the release managers and add them as required reviewers on the `prod` environment, as the README's deploy section describes. `.agents/hooks/agent-production-gate.sh` blocks an agent's shell commands that dispatch a `prod` deploy, run a Railway command with `prod` as its environment, or push a release tag. It does not read MCP tools. A release manager whose own agent session must do one of these starts the agent with `RELEASE_APPROVAL` set to the approval record, for example `RELEASE_APPROVAL=CHG-123 claude`.
94
- - **Review (tech lead):** replace `src/gen/` in `.agents/review.md` with this project's generated paths, then run `pnpm rules:sync`, which renders it to `REVIEW.md` for Claude Code Review. Once a month, rate the review findings and tune `.agents/review.md`.
94
+ - **Production gate (engineering leadership, with change management and compliance):** name the release managers and add them as required reviewers on the `prod` environment, as the README's deploy section describes. `.agents/hooks/agent-production-gate.sh` blocks an agent's shell commands that dispatch a `prod` deploy, run a Railway command with `prod` as its environment, or push a release tag. It does not read MCP tools. A release manager whose own agent session must do one of these starts the agent with `RELEASE_APPROVAL` set to the approval record, for example `RELEASE_APPROVAL=CHG-123 claude`. Any value lifts the gate except an empty value, `0`, `false`, and `no`, in any letter case.
95
+ - **Review (tech lead):** `.agents/review.md` names this stack's generated files to skip; add a path when the project gains a generated file, then run `pnpm rules:sync`, which renders it to `REVIEW.md` for Claude Code Review. Once a month, rate the review findings and tune `.agents/review.md`.
95
96
  - **People without Git experience:** connect GitHub to Claude (claude.ai or Cowork), so Claude commits `intent.md` for them.
96
97
 
97
98
  ## 7. Later, as the guardrails mature
98
99
 
99
- - Send the intent's path with `/sdlc` by hand first. Then build a job that runs it when an `intent.md` merges; this project ships no such job. The job runs this in the repository: `claude -p "/sdlc intent/<change>/intent.md" --permission-mode acceptEdits --allowedTools "Bash(git switch:*)" "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git log:*)" "Read" "Write" "Edit" "Glob" "Grep"`. Without `--permission-mode acceptEdits` the session stays in plan mode and writes nothing. The job then pushes the branch and opens the pull request with its own token; the product owner's first step is the review.
100
+ - Send the intent's path with `/sdlc` by hand first. Then turn on `Spec on intent merge` (step 8).
100
101
  - Make auto mode the default for routine work: a tight `spec.md`, a small blast radius, and code the tests already cover.
101
- - Replace `bands.yaml` with this project's metric, add a unit-tested detection script that reads it, and add the trigger that runs it.
102
+ - Set the metric in `bands.yaml`, then turn on `Control band` (step 8).
103
+
104
+ ## 8. Claude in CI
105
+
106
+ **Who:** a repository admin.
107
+
108
+ Each workflow below stays off until the repository variable `CLAUDE_CI_ENABLED` is `true`; until then nothing runs, on a schedule or otherwise, and nothing calls a model. When it is on, each needs one secret: `CLAUDE_CODE_OAUTH_TOKEN`, a Claude subscription token from `claude setup-token`, or `ANTHROPIC_API_KEY`, an API key. Either works; with neither set the job fails and says so. The jobs run the small model with a turn cap. Jobs that write install the Claude GitHub App from step 4 on the repository, and every change they make arrives as a pull request.
109
+
110
+ - **`Agent evals`:** runs `pnpm evals:run` when a pull request changes `AGENTS.md`, `CLAUDE.md`, `.agents`, `.claude`, or `.cursor`, and every night. The job fails below the pass threshold, and it needs `claude` on the `PATH` of the job.
111
+ - **`Spec on intent merge`:** when an `intent.md` reaches `main` with `Status: draft.` or `Status: accepted.` and no `spec.md` beside it, which is how the product owner accepts it, runs `/sdlc intent/<change>/intent.md`, so that `spec.md` arrives as a pull request for the product owner.
112
+ - **`Claude fix loop`:** when a person with write access comments `@claude` on a line of a pull request from this repository, Claude addresses the comment and pushes to that branch. It cannot approve or merge.
113
+ - **`triage` job of `Verify`:** when a pull request from this repository fails a check, reads the failed logs with the `Read` tool only and posts a three-line summary.
114
+ - **`Control band`:** every day, runs the command in the repository variable `CONTROL_BAND_METRIC_COMMAND`, which writes `metric-values.json` as `{"baseline": [...], "recent": [...]}`, then `pnpm bands:check metric-values.json`. A tier whose action is `diagnose` or `propose` runs `/sdlc` with the finding, and the `pull_request` route opens an intent pull request. It never acts on production.
115
+
116
+ On a machine, `pnpm evals:run` runs the evals with the developer's own Claude login, and `pnpm loop:measure` reports the loop's measures. Neither is part of `pnpm verify`.
117
+
118
+ **Check:** with `CLAUDE_CI_ENABLED` unset, **Actions** shows these jobs as skipped.
119
+
120
+ ## References
121
+
122
+ - [Set up Claude Code for your organization](https://code.claude.com/docs/en/admin-setup)
123
+ - [Settings reference and precedence](https://code.claude.com/docs/en/settings)
124
+ - [Server-managed settings](https://code.claude.com/docs/en/server-managed-settings)
125
+ - [Permissions](https://code.claude.com/docs/en/permissions)
126
+ - [Sandboxing](https://code.claude.com/docs/en/sandboxing)
127
+ - [Hooks guide](https://code.claude.com/docs/en/hooks-guide)
128
+ - [Hooks reference](https://code.claude.com/docs/en/hooks)
129
+ - [Skills](https://code.claude.com/docs/en/skills)
130
+ - [Plugins and private marketplaces](https://code.claude.com/docs/en/plugin-marketplaces)
131
+ - [Managed MCP](https://code.claude.com/docs/en/managed-mcp)
132
+ - [Enterprise deployment overview](https://code.claude.com/docs/en/third-party-integrations)
133
+ - [Enterprise network configuration](https://code.claude.com/docs/en/network-config)
134
+ - [Monitoring with OpenTelemetry](https://code.claude.com/docs/en/monitoring-usage)
135
+ - [Analytics dashboard](https://code.claude.com/docs/en/analytics)
136
+ - [Compliance API](https://platform.claude.com/docs/en/manage-claude/compliance-api)
137
+ - [Security model](https://code.claude.com/docs/en/security)
@@ -1,9 +1,9 @@
1
- # Example. Replace it with this project's metric, and add a version-controlled, unit-tested detection script that
2
- # reads this file. Detection stays deterministic, with no model involved.
1
+ # Detection settings for one metric: the tiers' actions, tools, and routes. `pnpm bands:check <file>` reads this file.
2
+ # The metric is this project's to set. Tiers are sample standard deviations from the baseline's mean.
3
3
  metric: ci_test_failure_rate
4
4
  baseline: rolling_30d
5
5
  rules: western_electric
6
6
  tiers:
7
7
  1sigma: {action: log}
8
8
  2sigma: {action: diagnose, tools: "Read,Grep,Bash(gh run view *)"}
9
- 3sigma: {action: propose, routes: [pull_request, runbook:rollback-deploy]}
9
+ 3sigma: {action: propose, routes: [pull_request]}
@@ -4,6 +4,7 @@ This folder is the intent home. Every change starts here as an `intent.md`, and
4
4
 
5
5
  - Each change has its own folder, `intent/<change>/`, where `<change>` is a short kebab-case name. The folder holds `intent.md` (Plan), then `spec.md` (Design), then `plan.md` (Build).
6
6
  - The playbooks in `.agents/skills/sdlc/playbooks/` say who writes and who accepts each file.
7
+ - A change is `done` when the tree meets every numbered requirement of its `spec.md`. The agent sets `Status: done.` in `intent.md` and `spec.md` in the pull request that meets the last requirement, and the code owner's approval of that pull request accepts it.
7
8
 
8
9
  ## Which file holds what
9
10
 
@@ -1,3 +1,4 @@
1
1
  {
2
- "$schema": "https://unpkg.com/knip@6/schema.json"
2
+ "$schema": "https://unpkg.com/knip@6/schema.json",
3
+ "ignoreDependencies": ["@swc/core"]
3
4
  }
@@ -1,6 +1,7 @@
1
1
  engineStrict: true
2
2
  savePrefix: ""
3
3
  allowBuilds:
4
+ "@swc/core": false
4
5
  esbuild: true
5
6
  unrs-resolver: true
6
7
  overrides:
@@ -13,31 +14,9 @@ overrides:
13
14
  "minimatch@<11.0.1": ^11.0.1
14
15
  minimumReleaseAgeExclude:
15
16
  - "@next-friday/commitlint-config-friday@4.0.0"
16
- - "@next-friday/eslint-config-friday@5.0.0"
17
17
  - "@next-friday/eslint-config-friday@5.1.0"
18
18
  - "@next-friday/prettier-config-friday@4.0.0"
19
19
  - "@next-friday/eslint-plugin-friday@1.1.3"
20
- packageExtensions:
21
- payload:
22
- peerDependenciesMeta:
23
- graphql:
24
- optional: true
25
- "@payloadcms/next":
26
- peerDependenciesMeta:
27
- graphql:
28
- optional: true
29
- "@payloadcms/graphql":
30
- peerDependenciesMeta:
31
- graphql:
32
- optional: true
33
- graphql-http:
34
- peerDependenciesMeta:
35
- graphql:
36
- optional: true
37
- graphql-scalars:
38
- peerDependenciesMeta:
39
- graphql:
40
- optional: true
41
20
  peerDependencyRules:
42
21
  ignoreMissing:
43
22
  - graphql
@@ -0,0 +1,27 @@
1
+ # Roll back a deployment
2
+
3
+ Returns production to the commit it ran before the current one.
4
+
5
+ **Who runs it:** a release manager. It is a production action: the `prod` environment's required reviewers approve the run, and an agent reports the command but never runs it.
6
+
7
+ ## Command
8
+
9
+ ```sh
10
+ gh workflow run deploy.yml --ref main --field environment=prod --field commit_sha=<previous commit SHA>
11
+ ```
12
+
13
+ `.github/workflows/deploy.yml` accepts any commit that is on `main`, has a successful CI run on `main`, and has a successful deployment to `uat`. A commit that ran in production before meets all three. The workflow checks out that commit, deploys it with `railway up`, and waits for `/health`.
14
+
15
+ Find the previous commit SHA in the deploy workflow's run history: the second most recent successful run titled `Deploy <SHA> to prod`.
16
+
17
+ ```sh
18
+ gh run list --workflow deploy.yml --branch main --status success --json displayTitle --jq '[.[] | select(.displayTitle | endswith(" to prod"))][1].displayTitle | split(" ")[1]'
19
+ ```
20
+
21
+ ## Rehearse
22
+
23
+ Run the same command with `environment=uat` and the commit SHA that `uat` ran before its current one, then check that `/health` answers on the `uat` URL. The `uat` run needs a successful `dev` deployment of that commit. Rehearse after each change to `deploy.yml`, and on a regular schedule.
24
+
25
+ ## After the rollback
26
+
27
+ Check that `/health` answers on the production URL, then open an intent for the fault that caused the rollback.