@next-friday/create-app 9.1.0 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/main.mjs +135 -96
- package/package.json +8 -6
- package/templates/base/.agents/hooks/agent-mcp-gate.sh +7 -2
- package/templates/base/.agents/hooks/agent-production-gate.sh +6 -1
- package/templates/base/.agents/hooks/agent-shell-gate.sh +1 -181
- package/templates/base/.agents/hooks/agent-test-edit-gate.sh +12 -3
- package/templates/base/.agents/review.md +2 -2
- package/templates/base/.agents/rules/no-suppression.md +1 -1
- package/templates/base/.agents/skill-evals/README.md +42 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/case.yaml +12 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/01-the-reply-explains-why-pnpm.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/02-no-file-in-the-project.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/03-no-commit-is-made-nothing.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/04-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/05-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/graders/06-everything-the-reply-states-as.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/answers-question-without-writing/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/case.yaml +12 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/01-work-happens-on-the-plan-branch.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/02-the-plan-is-implemented-and-checked.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/03-the-branch-is-pushed.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/04-the-reply-lists-three-playbooks.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/05-no-approval-and-no-merge.md +7 -0
- 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
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/graders/07-the-plan-names-the-engineer.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-continues-from-an-accepted-plan/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/case.yaml +71 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/01-the-reply-asks-numbered-questions.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/02-no-plan-before-the-answers.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/03-no-question-depends-on-another.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/04-no-file-or-commit.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/graders/05-the-reply-is-in-thai.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-interviews-before-planning/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/case.yaml +68 -0
- package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/fixture.md +1 -0
- 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
- package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/graders/02-no-source-file-or-commit.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/graders/03-the-reply-names-the-gate.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/graders/04-the-reply-is-in-thai.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/build-plans-and-waits-for-the-engineer/prompt.md +10 -0
- package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/case.yaml +8 -0
- package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/graders/01-no-deployment-is-started.md +7 -0
- 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
- 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
- package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/graders/04-the-reply-is-in-the-language.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/deploy-stops-at-the-production-gate/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/case.yaml +13 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/01-a-file-intentkebabcasenameintentmd-exists-with.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/02-the-reply-shows-the-draft.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/03-no-commit-is-made-nothing.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/04-reply-lists-the-playbook-steps.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/05-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/06-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/graders/07-the-drafts-open-questions-section.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/drafts-intent-and-waits-for-yes/prompt.md +10 -0
- package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/case.yaml +34 -0
- package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/fixture.md +1 -0
- 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
- 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
- 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
- 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
- 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
- package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/graders/06-the-reply-is-in-thai.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/fix-reproduces-finds-the-cause-and-waits-for-the-engineer/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/case.yaml +12 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/01-the-first-message-restates-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/02-the-reply-asks-numbered-questions.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/03-no-intentmd-is-written-before.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/04-reply-lists-the-playbook-steps.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/05-no-commit-is-made-nothing.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/06-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/07-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/graders/08-no-question-in-the-round.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/interviews-before-writing-intent/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/case.yaml +14 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/01-the-intent-has-the-five-headings.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/02-problem-holds-the-error-and-where.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/03-unverified-cause-is-an-open-question.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/04-no-source-file-is-changed.md +7 -0
- 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
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/graders/06-the-person-is-asked-no-question.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/maintain-writes-intent-from-a-finding/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/case.yaml +12 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/01-the-reply-follows-the-plan.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/02-the-reply-does-not-tell.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/03-no-file-is-created-or.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/04-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/graders/05-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/reported-problem-starts-the-plan/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/case.yaml +11 -0
- package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/fixture.md +1 -0
- 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
- package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/graders/02-the-reply-names-the-closest-row.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/graders/03-the-reply-is-short-and-in-thai.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/request-that-fits-no-row/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/case.yaml +79 -0
- package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/01-findings-have-pass-severity-and-location.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/02-no-approval-and-no-merge.md +7 -0
- 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
- package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/graders/04-nothing-is-pushed-or-changed.md +7 -0
- 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
- package/templates/base/.agents/skill-evals/sdlc/review-reports-findings-and-never-merges/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/case.yaml +42 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/01-no-spec-is-written.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/02-no-commit-is-made.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/03-the-reply-says-not-merged.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/04-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/graders/05-the-reply-is-short.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/spec-for-unmerged-intent-stops/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/case.yaml +12 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/01-no-intentmd-or-any-other.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/02-no-commit-is-made-nothing.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/03-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/04-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/graders/05-the-reply-says-that-work.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/statement-without-command-starts-no-work/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/case.yaml +42 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/fixture.md +1 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/01-the-spec-has-the-five-headings.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/02-policies-has-one-line-per-policy.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/03-no-policy-is-called-unwritten.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/04-a-branch-is-pushed-for-review.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/05-the-reply-names-the-gate.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/06-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/07-no-merge-is-made.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/graders/08-the-four-policies-are-read-before-writing.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc/writes-spec-from-merged-intent/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/case.yaml +11 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/01-the-reply-says-that-work.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/02-the-reply-gives-one-example.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/03-the-reply-lists-the-project.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/04-no-file-is-created-or.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/05-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/graders/06-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/explains-how-to-start-work/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/case.yaml +10 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/01-the-reply-says-that-this.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/02-the-reply-does-not-describe.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/03-no-file-is-created-or.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/04-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/graders/05-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/unknown-playbook-is-not-invented/prompt.md +8 -0
- package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/case.yaml +11 -0
- package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/01-the-reply-says-to-send.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/02-no-file-is-created-or.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/03-the-reply-is-in-the.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/graders/04-every-path-in-the-reply.md +7 -0
- package/templates/base/.agents/skill-evals/sdlc-help/work-request-is-sent-to-sdlc/prompt.md +8 -0
- package/templates/base/.agents/skills/sdlc/SKILL.md +25 -21
- package/templates/base/.agents/skills/sdlc/playbooks/build.md +13 -8
- package/templates/base/.agents/skills/sdlc/playbooks/deploy.md +2 -2
- package/templates/base/.agents/skills/sdlc/playbooks/design.md +4 -4
- package/templates/base/.agents/skills/sdlc/playbooks/fix.md +23 -0
- package/templates/base/.agents/skills/sdlc/playbooks/maintain.md +2 -3
- package/templates/base/.agents/skills/sdlc/playbooks/open-pr.md +3 -3
- package/templates/base/.agents/skills/sdlc/playbooks/plan.md +2 -2
- package/templates/base/.agents/skills/sdlc/playbooks/review.md +2 -2
- package/templates/base/.agents/skills/sdlc-help/SKILL.md +3 -1
- package/templates/base/.claude/managed-settings.example.json +2 -2
- package/templates/base/.claude/settings.json +0 -13
- package/templates/base/.claude/skills/sdlc/SKILL.md +25 -21
- package/templates/base/.claude/skills/sdlc/playbooks/build.md +13 -8
- package/templates/base/.claude/skills/sdlc/playbooks/deploy.md +2 -2
- package/templates/base/.claude/skills/sdlc/playbooks/design.md +4 -4
- package/templates/base/.claude/skills/sdlc/playbooks/fix.md +23 -0
- package/templates/base/.claude/skills/sdlc/playbooks/maintain.md +2 -3
- package/templates/base/.claude/skills/sdlc/playbooks/open-pr.md +3 -3
- package/templates/base/.claude/skills/sdlc/playbooks/plan.md +2 -2
- package/templates/base/.claude/skills/sdlc/playbooks/review.md +2 -2
- package/templates/base/.claude/skills/sdlc-help/SKILL.md +3 -1
- package/templates/base/.cursor/hooks.json +0 -6
- package/templates/base/.cursor/rules/no-suppression.mdc +1 -1
- package/templates/base/.cursor/skills/sdlc/SKILL.md +25 -21
- package/templates/base/.cursor/skills/sdlc/playbooks/build.md +13 -8
- package/templates/base/.cursor/skills/sdlc/playbooks/deploy.md +2 -2
- package/templates/base/.cursor/skills/sdlc/playbooks/design.md +4 -4
- package/templates/base/.cursor/skills/sdlc/playbooks/fix.md +23 -0
- package/templates/base/.cursor/skills/sdlc/playbooks/maintain.md +2 -3
- package/templates/base/.cursor/skills/sdlc/playbooks/open-pr.md +3 -3
- package/templates/base/.cursor/skills/sdlc/playbooks/plan.md +2 -2
- package/templates/base/.cursor/skills/sdlc/playbooks/review.md +2 -2
- package/templates/base/.cursor/skills/sdlc-help/SKILL.md +3 -1
- package/templates/base/.github/ISSUE_TEMPLATE/documentation.yml +1 -1
- package/templates/base/.github/dependabot.yml +1 -10
- package/templates/base/.github/file-filters.yml +3 -6
- package/templates/base/.github/workflows/agent-evals.yml +46 -0
- package/templates/base/.github/workflows/claude-fix-loop.yml +45 -0
- package/templates/base/.github/workflows/control-band.yml +115 -0
- package/templates/base/.github/workflows/dependency-review.yml +1 -0
- package/templates/base/.github/workflows/deploy.yml +4 -2
- package/templates/base/.github/workflows/osv-scanner.yml +0 -5
- package/templates/base/.github/workflows/pr-triage.yml +1 -1
- package/templates/base/.github/workflows/secret-scan.yml +4 -1
- package/templates/base/.github/workflows/spec-on-intent-merge.yml +108 -0
- package/templates/base/.github/workflows/validate-pr-title.yml +3 -2
- package/templates/base/.husky/pre-push +1 -8
- package/templates/base/REVIEW.md +2 -2
- package/templates/base/SETUP.md +44 -8
- package/templates/base/bands.yaml +3 -3
- package/templates/base/intent/README.md +1 -0
- package/templates/base/knip.json +2 -1
- package/templates/base/pnpm-workspace.yaml +1 -22
- package/templates/base/runbooks/rollback-deploy.md +27 -0
- package/templates/base/scripts/check-agent-gates.ts +251 -225
- package/templates/base/scripts/check-bands.ts +665 -0
- package/templates/base/scripts/check-plan.ts +1047 -0
- package/templates/base/scripts/measure-loop.ts +293 -0
- package/templates/base/scripts/run-agent-evals.ts +1186 -0
- package/templates/base/scripts/sync-agent-rules.ts +0 -8
- package/templates/nestjs/.dependency-cruiser.json +1 -1
- package/templates/nestjs/.github/ISSUE_TEMPLATE/bug.yml +5 -5
- package/templates/nestjs/.github/workflows/ci.yml +58 -9
- package/templates/nestjs/.github/workflows/sast.yml +0 -5
- package/templates/nestjs/AGENTS.md +16 -12
- package/templates/nestjs/CONTRIBUTING.md +3 -2
- package/templates/nestjs/Dockerfile +4 -4
- package/templates/nestjs/README.md +4 -6
- package/templates/nestjs/_gitignore +0 -1
- package/templates/nestjs/package.json +15 -13
- package/templates/nestjs/src/app.controller.test.ts +1 -0
- package/templates/nestjs/src/health/health.controller.test.ts +1 -0
- package/templates/nestjs/src/port.test.ts +1 -0
- package/templates/nestjs/test/app.e2e.test.ts +1 -0
- package/templates/nestjs/tsconfig.build.json +2 -3
- package/templates/nestjs/tsconfig.json +1 -3
- package/templates/nestjs/vitest.config.ts +0 -1
- package/templates/nestjs/vitest.e2e.config.ts +0 -1
- package/templates/nextjs/.dependency-cruiser.json +1 -1
- package/templates/nextjs/.github/ISSUE_TEMPLATE/bug.yml +1 -1
- package/templates/nextjs/.github/workflows/ci.yml +58 -9
- package/templates/nextjs/.github/workflows/sast.yml +0 -5
- package/templates/nextjs/AGENTS.md +16 -12
- package/templates/nextjs/CONTRIBUTING.md +3 -2
- package/templates/nextjs/Dockerfile +2 -2
- package/templates/nextjs/README.md +5 -3
- package/templates/nextjs/app/layout.tsx +2 -2
- package/templates/nextjs/app/page.test.ts +1 -1
- package/templates/nextjs/app/page.tsx +1 -1
- package/templates/nextjs/package.json +9 -8
- package/templates/nextjs/test/home.e2e.test.ts +3 -7
- package/templates/nextjs/tsconfig.json +0 -3
- package/templates/nodejs/.dependency-cruiser.json +1 -1
- package/templates/nodejs/.github/ISSUE_TEMPLATE/bug.yml +5 -5
- package/templates/nodejs/.github/workflows/ci.yml +58 -9
- package/templates/nodejs/.github/workflows/sast.yml +0 -5
- package/templates/nodejs/AGENTS.md +16 -11
- package/templates/nodejs/CONTRIBUTING.md +4 -3
- package/templates/nodejs/Dockerfile +3 -3
- package/templates/nodejs/README.md +4 -4
- package/templates/nodejs/_gitignore +0 -1
- package/templates/nodejs/package.json +11 -9
- package/templates/nodejs/src/server.test.ts +23 -0
- package/templates/nodejs/src/server.ts +2 -2
- package/templates/nodejs/tsconfig.build.json +2 -3
- package/templates/nodejs/tsconfig.json +0 -4
- package/templates/payload/.agents/agents/verifier.md +1 -1
- package/templates/payload/.agents/review.md +21 -0
- package/templates/payload/.claude/agents/verifier.md +1 -1
- package/templates/payload/.cursor/agents/verifier.md +1 -1
- package/templates/payload/.dependency-cruiser.json +1 -1
- package/templates/payload/.github/ISSUE_TEMPLATE/bug.yml +1 -1
- package/templates/payload/.github/workflows/ci.yml +75 -10
- package/templates/payload/.github/workflows/sast.yml +0 -5
- package/templates/payload/AGENTS.md +21 -17
- package/templates/payload/CONTRIBUTING.md +4 -3
- package/templates/payload/Dockerfile +2 -2
- package/templates/payload/README.md +8 -4
- package/templates/payload/REVIEW.md +21 -0
- package/templates/payload/package.json +9 -7
- package/templates/payload/src/app/(frontend)/layout.tsx +2 -2
- package/templates/payload/src/app/(frontend)/page.test.ts +1 -1
- package/templates/payload/src/app/(frontend)/page.tsx +1 -1
- package/templates/payload/src/app/favicon.ico +0 -0
- package/templates/payload/src/app/health/route.test.ts +20 -2
- package/templates/payload/src/app/health/route.ts +9 -2
- package/templates/payload/src/collections/media.test.ts +36 -1
- package/templates/payload/src/collections/media.ts +1 -1
- package/templates/payload/src/payload.config.test.ts +15 -0
- package/templates/payload/test/home.e2e.test.ts +3 -7
- package/templates/payload/tsconfig.json +0 -1
- package/templates/turborepo/.agents/agents/verifier.md +1 -1
- package/templates/turborepo/.agents/review.md +21 -0
- package/templates/turborepo/.claude/agents/verifier.md +1 -1
- package/templates/turborepo/.cursor/agents/verifier.md +1 -1
- package/templates/turborepo/.dockerignore +9 -4
- package/templates/turborepo/.github/ISSUE_TEMPLATE/bug.yml +16 -1
- package/templates/turborepo/.github/dependabot.yml +1 -10
- package/templates/turborepo/.github/scripts/affected-apps.sh +5 -23
- package/templates/turborepo/.github/workflows/ci.yml +140 -103
- package/templates/turborepo/.github/workflows/deploy.yml +24 -23
- package/templates/turborepo/.github/workflows/sast.yml +0 -5
- package/templates/turborepo/AGENTS.md +21 -17
- package/templates/turborepo/CONTRIBUTING.md +6 -4
- package/templates/turborepo/README.md +8 -8
- package/templates/turborepo/REVIEW.md +21 -0
- package/templates/turborepo/apps/app/.dependency-cruiser.json +1 -1
- package/templates/turborepo/apps/app/AGENTS.md +9 -0
- package/templates/turborepo/apps/app/Dockerfile +2 -2
- package/templates/turborepo/apps/app/app/layout.tsx +2 -2
- package/templates/turborepo/apps/app/app/page.test.ts +1 -1
- package/templates/turborepo/apps/app/app/page.tsx +1 -1
- package/templates/turborepo/apps/app/package.json +3 -3
- package/templates/turborepo/apps/app/test/home.e2e.test.ts +3 -7
- package/templates/turborepo/apps/app/tsconfig.json +0 -3
- package/templates/turborepo/apps/backoffice/.dependency-cruiser.json +1 -1
- package/templates/turborepo/apps/backoffice/AGENTS.md +9 -0
- package/templates/turborepo/apps/backoffice/Dockerfile +2 -2
- package/templates/turborepo/apps/backoffice/package.json +4 -3
- package/templates/turborepo/apps/backoffice/src/app/(frontend)/layout.tsx +2 -2
- package/templates/turborepo/apps/backoffice/src/app/(frontend)/page.test.ts +1 -1
- package/templates/turborepo/apps/backoffice/src/app/(frontend)/page.tsx +1 -1
- package/templates/turborepo/apps/backoffice/src/app/favicon.ico +0 -0
- package/templates/turborepo/apps/backoffice/src/app/health/route.test.ts +20 -2
- package/templates/turborepo/apps/backoffice/src/app/health/route.ts +10 -2
- package/templates/turborepo/apps/backoffice/src/collections/media.test.ts +36 -1
- package/templates/turborepo/apps/backoffice/src/collections/media.ts +1 -1
- package/templates/turborepo/apps/backoffice/src/environment.test.ts +19 -0
- package/templates/turborepo/apps/backoffice/src/payload.config.test.ts +15 -0
- package/templates/turborepo/apps/backoffice/test/home.e2e.test.ts +3 -7
- package/templates/turborepo/apps/backoffice/tsconfig.json +0 -1
- package/templates/turborepo/knip.json +4 -2
- package/templates/turborepo/package.json +15 -15
- package/templates/turborepo/pnpm-workspace.yaml +1 -22
- package/templates/turborepo/turbo.json +32 -11
- package/templates/base/.agents/hooks/agent-suppression-gate.sh +0 -45
- package/templates/base/.claude/rules/agents-guide.md +0 -1
- package/templates/base/scripts/check-human-gates.ts +0 -383
- package/templates/base/scripts/check-intent.ts +0 -391
- package/templates/nextjs/knip.json +0 -4
- package/templates/payload/src/collections/users.test.ts +0 -10
- 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 *)"
|
|
@@ -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 "$
|
|
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::$
|
|
127
|
+
echo "::error::$health_url did not respond"
|
|
126
128
|
exit 1
|
|
@@ -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
|
|
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
|
|
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 || {
|
package/templates/base/REVIEW.md
CHANGED
|
@@ -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
|
|
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
|
|
21
|
+
Generated files, such as `pnpm-lock.yaml`, and anything CI already enforces.
|
package/templates/base/SETUP.md
CHANGED
|
@@ -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):**
|
|
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
|
|
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
|
-
-
|
|
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
|
-
#
|
|
2
|
-
#
|
|
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
|
|
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
|
|
package/templates/base/knip.json
CHANGED
|
@@ -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.
|