@glxmart/boss-cli 1.0.0 → 1.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.
Files changed (317) hide show
  1. package/README.md +0 -1
  2. package/assets/claude-md/docs/conductor.md +139 -0
  3. package/assets/claude-md/docs/initialization.md +2 -2
  4. package/assets/claude-md/docs/workers.md +33 -54
  5. package/assets/claude-md/docs/workflow.md +23 -59
  6. package/assets/claude-md/template.md +198 -756
  7. package/assets/git-hooks/commit-msg.sh +4 -8
  8. package/assets/git-hooks/pre-commit.sh +0 -4
  9. package/assets/git-hooks/pre-push.sh +21 -0
  10. package/assets/github-workflows/CODEOWNERS +21 -2
  11. package/assets/github-workflows/boss-ci.yml +163 -23
  12. package/assets/github-workflows/boss-gates.yml +100 -13
  13. package/assets/template-docs/nextjs-app-turbo.md +412 -61
  14. package/assets/template-loader/gitignore +14 -0
  15. package/assets/worker-configs/architect/.claude/skills/conductor-orchestration.md +635 -0
  16. package/assets/worker-configs/architect/.claude/skills/spec-kit-workflow.md +827 -0
  17. package/assets/worker-configs/architect/CLAUDE.md +99 -38
  18. package/assets/worker-configs/clarifier/.claude/skills/conductor-orchestration.md +635 -0
  19. package/assets/worker-configs/clarifier/.claude/skills/spec-kit-workflow.md +827 -0
  20. package/assets/worker-configs/clarifier/CLAUDE.md +81 -40
  21. package/assets/worker-configs/code-reviewer/.claude/skills/nextjs-turbo-stack.md +1017 -0
  22. package/assets/worker-configs/code-reviewer/.claude/skills/spec-kit-workflow.md +827 -0
  23. package/assets/worker-configs/code-reviewer/.claude/skills/test-first-methodology.md +745 -0
  24. package/assets/worker-configs/code-reviewer/CLAUDE.md +85 -79
  25. package/assets/worker-configs/consolidator/.claude/skills/conductor-orchestration.md +635 -0
  26. package/assets/worker-configs/consolidator/.claude/skills/spec-kit-workflow.md +827 -0
  27. package/assets/worker-configs/consolidator/CLAUDE.md +94 -88
  28. package/assets/worker-configs/developer-backend/.claude/skills/nextjs-turbo-stack.md +1017 -0
  29. package/assets/worker-configs/developer-backend/.claude/skills/spec-kit-workflow.md +827 -0
  30. package/assets/worker-configs/developer-backend/.claude/skills/test-first-methodology.md +745 -0
  31. package/assets/worker-configs/developer-backend/CLAUDE.md +156 -56
  32. package/assets/worker-configs/developer-frontend/.claude/skills/nextjs-turbo-stack.md +1017 -0
  33. package/assets/worker-configs/developer-frontend/.claude/skills/spec-kit-workflow.md +827 -0
  34. package/assets/worker-configs/developer-frontend/.claude/skills/test-first-methodology.md +745 -0
  35. package/assets/worker-configs/developer-frontend/CLAUDE.md +152 -54
  36. package/assets/worker-configs/developer-fullstack/.claude/skills/nextjs-turbo-stack.md +1017 -0
  37. package/assets/worker-configs/developer-fullstack/.claude/skills/spec-kit-workflow.md +827 -0
  38. package/assets/worker-configs/developer-fullstack/.claude/skills/test-first-methodology.md +745 -0
  39. package/assets/worker-configs/developer-fullstack/CLAUDE.md +155 -57
  40. package/assets/worker-configs/devops-engineer/.claude/skills/infrastructure-as-code.md +794 -0
  41. package/assets/worker-configs/devops-engineer/.claude/skills/spec-kit-workflow.md +827 -0
  42. package/assets/worker-configs/devops-engineer/CLAUDE.md +92 -85
  43. package/assets/worker-configs/planner/.claude/skills/conductor-orchestration.md +635 -0
  44. package/assets/worker-configs/planner/.claude/skills/spec-kit-workflow.md +827 -0
  45. package/assets/worker-configs/planner/CLAUDE.md +143 -46
  46. package/assets/worker-configs/product-owner/CLAUDE.md +72 -82
  47. package/assets/worker-configs/reviewer/.claude/skills/conductor-orchestration.md +635 -0
  48. package/assets/worker-configs/reviewer/.claude/skills/spec-kit-workflow.md +827 -0
  49. package/assets/worker-configs/reviewer/CLAUDE.md +108 -50
  50. package/assets/worker-configs/security-engineer/.claude/skills/spec-kit-workflow.md +827 -0
  51. package/assets/worker-configs/security-engineer/CLAUDE.md +83 -83
  52. package/assets/worker-configs/spec-writer/.claude/skills/conductor-orchestration.md +635 -0
  53. package/assets/worker-configs/spec-writer/.claude/skills/spec-kit-workflow.md +827 -0
  54. package/assets/worker-configs/spec-writer/CLAUDE.md +107 -48
  55. package/assets/worker-configs/technical-writer/.claude/skills/nextjs-turbo-stack.md +1017 -0
  56. package/assets/worker-configs/technical-writer/.claude/skills/spec-kit-workflow.md +827 -0
  57. package/assets/worker-configs/technical-writer/CLAUDE.md +91 -81
  58. package/assets/worker-configs/tester/.claude/skills/nextjs-turbo-stack.md +1017 -0
  59. package/assets/worker-configs/tester/.claude/skills/spec-kit-workflow.md +827 -0
  60. package/assets/worker-configs/tester/.claude/skills/test-first-methodology.md +745 -0
  61. package/assets/worker-configs/tester/CLAUDE.md +141 -52
  62. package/dist/assets/claude-md/docs/conductor.md +139 -0
  63. package/dist/assets/claude-md/docs/initialization.md +2 -2
  64. package/dist/assets/claude-md/docs/workers.md +33 -54
  65. package/dist/assets/claude-md/docs/workflow.md +23 -59
  66. package/dist/assets/claude-md/template.md +198 -756
  67. package/dist/assets/git-hooks/commit-msg.sh +4 -8
  68. package/dist/assets/git-hooks/pre-commit.sh +0 -4
  69. package/dist/assets/git-hooks/pre-push.sh +21 -0
  70. package/dist/assets/github-workflows/CODEOWNERS +21 -2
  71. package/dist/assets/github-workflows/boss-ci.yml +163 -23
  72. package/dist/assets/github-workflows/boss-gates.yml +100 -13
  73. package/dist/assets/template-docs/nextjs-app-turbo.md +412 -61
  74. package/dist/assets/template-loader/gitignore +14 -0
  75. package/dist/assets/worker-configs/architect/.claude/skills/conductor-orchestration.md +635 -0
  76. package/dist/assets/worker-configs/architect/.claude/skills/spec-kit-workflow.md +827 -0
  77. package/dist/assets/worker-configs/architect/CLAUDE.md +99 -38
  78. package/dist/assets/worker-configs/clarifier/.claude/skills/conductor-orchestration.md +635 -0
  79. package/dist/assets/worker-configs/clarifier/.claude/skills/spec-kit-workflow.md +827 -0
  80. package/dist/assets/worker-configs/clarifier/CLAUDE.md +81 -40
  81. package/dist/assets/worker-configs/code-reviewer/.claude/skills/nextjs-turbo-stack.md +1017 -0
  82. package/dist/assets/worker-configs/code-reviewer/.claude/skills/spec-kit-workflow.md +827 -0
  83. package/dist/assets/worker-configs/code-reviewer/.claude/skills/test-first-methodology.md +745 -0
  84. package/dist/assets/worker-configs/code-reviewer/CLAUDE.md +85 -79
  85. package/dist/assets/worker-configs/consolidator/.claude/skills/conductor-orchestration.md +635 -0
  86. package/dist/assets/worker-configs/consolidator/.claude/skills/spec-kit-workflow.md +827 -0
  87. package/dist/assets/worker-configs/consolidator/CLAUDE.md +94 -88
  88. package/dist/assets/worker-configs/developer-backend/.claude/skills/nextjs-turbo-stack.md +1017 -0
  89. package/dist/assets/worker-configs/developer-backend/.claude/skills/spec-kit-workflow.md +827 -0
  90. package/dist/assets/worker-configs/developer-backend/.claude/skills/test-first-methodology.md +745 -0
  91. package/dist/assets/worker-configs/developer-backend/CLAUDE.md +156 -56
  92. package/dist/assets/worker-configs/developer-frontend/.claude/skills/nextjs-turbo-stack.md +1017 -0
  93. package/dist/assets/worker-configs/developer-frontend/.claude/skills/spec-kit-workflow.md +827 -0
  94. package/dist/assets/worker-configs/developer-frontend/.claude/skills/test-first-methodology.md +745 -0
  95. package/dist/assets/worker-configs/developer-frontend/CLAUDE.md +152 -54
  96. package/dist/assets/worker-configs/developer-fullstack/.claude/skills/nextjs-turbo-stack.md +1017 -0
  97. package/dist/assets/worker-configs/developer-fullstack/.claude/skills/spec-kit-workflow.md +827 -0
  98. package/dist/assets/worker-configs/developer-fullstack/.claude/skills/test-first-methodology.md +745 -0
  99. package/dist/assets/worker-configs/developer-fullstack/CLAUDE.md +155 -57
  100. package/dist/assets/worker-configs/devops-engineer/.claude/skills/infrastructure-as-code.md +794 -0
  101. package/dist/assets/worker-configs/devops-engineer/.claude/skills/spec-kit-workflow.md +827 -0
  102. package/dist/assets/worker-configs/devops-engineer/CLAUDE.md +92 -85
  103. package/dist/assets/worker-configs/planner/.claude/skills/conductor-orchestration.md +635 -0
  104. package/dist/assets/worker-configs/planner/.claude/skills/spec-kit-workflow.md +827 -0
  105. package/dist/assets/worker-configs/planner/CLAUDE.md +143 -46
  106. package/dist/assets/worker-configs/product-owner/CLAUDE.md +72 -82
  107. package/dist/assets/worker-configs/reviewer/.claude/skills/conductor-orchestration.md +635 -0
  108. package/dist/assets/worker-configs/reviewer/.claude/skills/spec-kit-workflow.md +827 -0
  109. package/dist/assets/worker-configs/reviewer/CLAUDE.md +108 -50
  110. package/dist/assets/worker-configs/security-engineer/.claude/skills/spec-kit-workflow.md +827 -0
  111. package/dist/assets/worker-configs/security-engineer/CLAUDE.md +83 -83
  112. package/dist/assets/worker-configs/spec-writer/.claude/skills/conductor-orchestration.md +635 -0
  113. package/dist/assets/worker-configs/spec-writer/.claude/skills/spec-kit-workflow.md +827 -0
  114. package/dist/assets/worker-configs/spec-writer/CLAUDE.md +107 -48
  115. package/dist/assets/worker-configs/technical-writer/.claude/skills/nextjs-turbo-stack.md +1017 -0
  116. package/dist/assets/worker-configs/technical-writer/.claude/skills/spec-kit-workflow.md +827 -0
  117. package/dist/assets/worker-configs/technical-writer/CLAUDE.md +91 -81
  118. package/dist/assets/worker-configs/tester/.claude/skills/nextjs-turbo-stack.md +1017 -0
  119. package/dist/assets/worker-configs/tester/.claude/skills/spec-kit-workflow.md +827 -0
  120. package/dist/assets/worker-configs/tester/.claude/skills/test-first-methodology.md +745 -0
  121. package/dist/assets/worker-configs/tester/CLAUDE.md +141 -52
  122. package/dist/commands/__tests__/bootstrap.test.js +51 -51
  123. package/dist/commands/__tests__/bootstrap.test.js.map +1 -1
  124. package/dist/commands/bootstrap.d.ts.map +1 -1
  125. package/dist/commands/bootstrap.js +23 -20
  126. package/dist/commands/bootstrap.js.map +1 -1
  127. package/dist/commands/doctor.js +33 -9
  128. package/dist/commands/doctor.js.map +1 -1
  129. package/dist/commands/templates.d.ts +1 -1
  130. package/dist/commands/templates.d.ts.map +1 -1
  131. package/dist/commands/templates.js +1 -1
  132. package/dist/commands/templates.js.map +1 -1
  133. package/dist/constants.d.ts +2 -2
  134. package/dist/constants.d.ts.map +1 -1
  135. package/dist/constants.js +1 -1
  136. package/dist/constants.js.map +1 -1
  137. package/dist/generators/__tests__/boss-config.test.js +4 -4
  138. package/dist/generators/__tests__/boss-config.test.js.map +1 -1
  139. package/dist/generators/__tests__/claude-folder.test.js +8 -8
  140. package/dist/generators/__tests__/claude-folder.test.js.map +1 -1
  141. package/dist/generators/__tests__/claude-md.test.js +25 -16
  142. package/dist/generators/__tests__/claude-md.test.js.map +1 -1
  143. package/dist/generators/__tests__/container-use-config.test.js +2 -2
  144. package/dist/generators/__tests__/container-use-config.test.js.map +1 -1
  145. package/dist/generators/__tests__/git-hooks.test.js.map +1 -1
  146. package/dist/generators/__tests__/github-workflows.test.js +10 -6
  147. package/dist/generators/__tests__/github-workflows.test.js.map +1 -1
  148. package/dist/generators/__tests__/mcp-config.test.js +6 -6
  149. package/dist/generators/__tests__/project-structure.test.js +2 -2
  150. package/dist/generators/__tests__/quality-gates.test.js +11 -3
  151. package/dist/generators/__tests__/quality-gates.test.js.map +1 -1
  152. package/dist/generators/__tests__/specify-structure.test.js +1 -1
  153. package/dist/generators/__tests__/specify-structure.test.js.map +1 -1
  154. package/dist/generators/__tests__/template-docs.test.js +1 -1
  155. package/dist/generators/__tests__/template-docs.test.js.map +1 -1
  156. package/dist/generators/__tests__/template-loader.test.js +209 -59
  157. package/dist/generators/__tests__/template-loader.test.js.map +1 -1
  158. package/dist/generators/__tests__/worker-configs.test.js +7 -7
  159. package/dist/generators/boss-config.d.ts.map +1 -1
  160. package/dist/generators/boss-config.js +46 -51
  161. package/dist/generators/boss-config.js.map +1 -1
  162. package/dist/generators/claude-folder.d.ts +1 -1
  163. package/dist/generators/claude-folder.d.ts.map +1 -1
  164. package/dist/generators/claude-folder.js +5 -5
  165. package/dist/generators/claude-folder.js.map +1 -1
  166. package/dist/generators/claude-md.d.ts.map +1 -1
  167. package/dist/generators/claude-md.js +83 -42
  168. package/dist/generators/claude-md.js.map +1 -1
  169. package/dist/generators/container-use-config.d.ts.map +1 -1
  170. package/dist/generators/container-use-config.js +5 -7
  171. package/dist/generators/container-use-config.js.map +1 -1
  172. package/dist/generators/docker-compose.d.ts.map +1 -1
  173. package/dist/generators/docker-compose.js.map +1 -1
  174. package/dist/generators/git-hooks.d.ts.map +1 -1
  175. package/dist/generators/git-hooks.js +2 -2
  176. package/dist/generators/git-hooks.js.map +1 -1
  177. package/dist/generators/github-workflows.js +3 -3
  178. package/dist/generators/github-workflows.js.map +1 -1
  179. package/dist/generators/mcp-config.d.ts.map +1 -1
  180. package/dist/generators/mcp-config.js +18 -16
  181. package/dist/generators/mcp-config.js.map +1 -1
  182. package/dist/generators/project-structure.d.ts +1 -1
  183. package/dist/generators/project-structure.d.ts.map +1 -1
  184. package/dist/generators/project-structure.js +2 -2
  185. package/dist/generators/project-structure.js.map +1 -1
  186. package/dist/generators/quality-gates.d.ts.map +1 -1
  187. package/dist/generators/quality-gates.js +13 -5
  188. package/dist/generators/quality-gates.js.map +1 -1
  189. package/dist/generators/specify-structure.d.ts.map +1 -1
  190. package/dist/generators/specify-structure.js +1 -2
  191. package/dist/generators/specify-structure.js.map +1 -1
  192. package/dist/generators/template-docs.js +2 -2
  193. package/dist/generators/template-docs.js.map +1 -1
  194. package/dist/generators/template-loader.d.ts.map +1 -1
  195. package/dist/generators/template-loader.js +259 -143
  196. package/dist/generators/template-loader.js.map +1 -1
  197. package/dist/generators/worker-configs.d.ts.map +1 -1
  198. package/dist/generators/worker-configs.js +7 -5
  199. package/dist/generators/worker-configs.js.map +1 -1
  200. package/dist/index.js +2 -2
  201. package/dist/index.js.map +1 -1
  202. package/dist/presets/__tests__/quality-presets.test.js +9 -5
  203. package/dist/presets/__tests__/quality-presets.test.js.map +1 -1
  204. package/dist/presets/quality-presets.d.ts.map +1 -1
  205. package/dist/presets/quality-presets.js +11 -11
  206. package/dist/presets/quality-presets.js.map +1 -1
  207. package/dist/types/index.d.ts +1 -0
  208. package/dist/types/index.d.ts.map +1 -1
  209. package/dist/types/index.js +2 -1
  210. package/dist/types/index.js.map +1 -1
  211. package/dist/types/internal.d.ts +69 -0
  212. package/dist/types/internal.d.ts.map +1 -0
  213. package/dist/types/internal.js +4 -0
  214. package/dist/types/internal.js.map +1 -0
  215. package/dist/utils/__tests__/file-system.test.js +1 -1
  216. package/dist/utils/__tests__/file-system.test.js.map +1 -1
  217. package/dist/utils/__tests__/git.test.js.map +1 -1
  218. package/dist/utils/__tests__/template-loader.test.js.map +1 -1
  219. package/dist/utils/__tests__/validators.test.js +1 -1
  220. package/dist/utils/__tests__/validators.test.js.map +1 -1
  221. package/dist/utils/file-system.d.ts.map +1 -1
  222. package/dist/utils/file-system.js +1 -4
  223. package/dist/utils/file-system.js.map +1 -1
  224. package/dist/utils/git.d.ts.map +1 -1
  225. package/dist/utils/git.js +17 -11
  226. package/dist/utils/git.js.map +1 -1
  227. package/dist/utils/prompts.d.ts.map +1 -1
  228. package/dist/utils/prompts.js +51 -39
  229. package/dist/utils/prompts.js.map +1 -1
  230. package/dist/utils/template-loader.d.ts +2 -1
  231. package/dist/utils/template-loader.d.ts.map +1 -1
  232. package/dist/utils/template-loader.js +11 -5
  233. package/dist/utils/template-loader.js.map +1 -1
  234. package/dist/utils/validators.d.ts.map +1 -1
  235. package/dist/utils/validators.js +16 -4
  236. package/dist/utils/validators.js.map +1 -1
  237. package/package.json +2 -2
  238. package/templates/nextjs-turbo-monorepo/base/README.md +167 -0
  239. package/templates/nextjs-turbo-monorepo/base/_gitignore +71 -0
  240. package/templates/nextjs-turbo-monorepo/base/_npmrc +12 -0
  241. package/templates/nextjs-turbo-monorepo/base/apps/admin/app/layout.tsx +19 -0
  242. package/templates/nextjs-turbo-monorepo/base/apps/admin/app/page.tsx +34 -0
  243. package/templates/nextjs-turbo-monorepo/base/apps/admin/next.config.ts +20 -0
  244. package/templates/nextjs-turbo-monorepo/base/apps/admin/package.json +42 -0
  245. package/templates/nextjs-turbo-monorepo/base/apps/admin/tsconfig.json +16 -0
  246. package/templates/nextjs-turbo-monorepo/base/apps/web/app/globals.css +59 -0
  247. package/templates/nextjs-turbo-monorepo/base/apps/web/app/layout.tsx +20 -0
  248. package/templates/nextjs-turbo-monorepo/base/apps/web/app/page.tsx +17 -0
  249. package/templates/nextjs-turbo-monorepo/base/apps/web/components.json +18 -0
  250. package/templates/nextjs-turbo-monorepo/base/apps/web/env.ts +45 -0
  251. package/templates/nextjs-turbo-monorepo/base/apps/web/next.config.ts +38 -0
  252. package/templates/nextjs-turbo-monorepo/base/apps/web/package.json +45 -0
  253. package/templates/nextjs-turbo-monorepo/base/apps/web/tsconfig.json +19 -0
  254. package/templates/nextjs-turbo-monorepo/base/apps/web/vitest.config.ts +28 -0
  255. package/templates/nextjs-turbo-monorepo/base/docker/Dockerfile.admin +76 -0
  256. package/templates/nextjs-turbo-monorepo/base/docker/Dockerfile.web +76 -0
  257. package/templates/nextjs-turbo-monorepo/base/docker/_dockerignore +48 -0
  258. package/templates/nextjs-turbo-monorepo/base/docker/docker-compose.yml +39 -0
  259. package/templates/nextjs-turbo-monorepo/base/package.json +62 -0
  260. package/templates/nextjs-turbo-monorepo/base/packages/auth/package.json +26 -0
  261. package/templates/nextjs-turbo-monorepo/base/packages/auth/src/config.ts +88 -0
  262. package/templates/nextjs-turbo-monorepo/base/packages/auth/src/index.ts +11 -0
  263. package/templates/nextjs-turbo-monorepo/base/packages/auth/src/types.ts +28 -0
  264. package/templates/nextjs-turbo-monorepo/base/packages/auth/tsconfig.json +9 -0
  265. package/templates/nextjs-turbo-monorepo/base/packages/config/eslint/library.js +35 -0
  266. package/templates/nextjs-turbo-monorepo/base/packages/config/eslint/nextjs.js +51 -0
  267. package/templates/nextjs-turbo-monorepo/base/packages/config/eslint/react-library.js +45 -0
  268. package/templates/nextjs-turbo-monorepo/base/packages/config/package.json +19 -0
  269. package/templates/nextjs-turbo-monorepo/base/packages/config/tailwind/base.ts +50 -0
  270. package/templates/nextjs-turbo-monorepo/base/packages/config/typescript/base.json +23 -0
  271. package/templates/nextjs-turbo-monorepo/base/packages/config/typescript/nextjs.json +17 -0
  272. package/templates/nextjs-turbo-monorepo/base/packages/config/typescript/react-library.json +11 -0
  273. package/templates/nextjs-turbo-monorepo/base/packages/database/package.json +32 -0
  274. package/templates/nextjs-turbo-monorepo/base/packages/database/prisma/schema.prisma +84 -0
  275. package/templates/nextjs-turbo-monorepo/base/packages/database/src/client.ts +16 -0
  276. package/templates/nextjs-turbo-monorepo/base/packages/database/src/index.ts +2 -0
  277. package/templates/nextjs-turbo-monorepo/base/packages/database/tsconfig.json +9 -0
  278. package/templates/nextjs-turbo-monorepo/base/packages/trpc/package.json +32 -0
  279. package/templates/nextjs-turbo-monorepo/base/packages/trpc/src/context.ts +17 -0
  280. package/templates/nextjs-turbo-monorepo/base/packages/trpc/src/index.ts +3 -0
  281. package/templates/nextjs-turbo-monorepo/base/packages/trpc/src/init.ts +34 -0
  282. package/templates/nextjs-turbo-monorepo/base/packages/trpc/src/routers/_app.ts +8 -0
  283. package/templates/nextjs-turbo-monorepo/base/packages/trpc/src/routers/user.ts +36 -0
  284. package/templates/nextjs-turbo-monorepo/base/packages/trpc/tsconfig.json +9 -0
  285. package/templates/nextjs-turbo-monorepo/base/packages/ui/.storybook/main.ts +19 -0
  286. package/templates/nextjs-turbo-monorepo/base/packages/ui/.storybook/preview.ts +15 -0
  287. package/templates/nextjs-turbo-monorepo/base/packages/ui/components.json +17 -0
  288. package/templates/nextjs-turbo-monorepo/base/packages/ui/package.json +62 -0
  289. package/templates/nextjs-turbo-monorepo/base/packages/ui/postcss.config.js +6 -0
  290. package/templates/nextjs-turbo-monorepo/base/packages/ui/src/components/index.ts +2 -0
  291. package/templates/nextjs-turbo-monorepo/base/packages/ui/src/components/ui/button.tsx +57 -0
  292. package/templates/nextjs-turbo-monorepo/base/packages/ui/src/components/ui/card.tsx +76 -0
  293. package/templates/nextjs-turbo-monorepo/base/packages/ui/src/hooks/index.ts +2 -0
  294. package/templates/nextjs-turbo-monorepo/base/packages/ui/src/lib/utils.ts +6 -0
  295. package/templates/nextjs-turbo-monorepo/base/packages/ui/src/styles/globals.css +59 -0
  296. package/templates/nextjs-turbo-monorepo/base/packages/ui/tailwind.config.ts +15 -0
  297. package/templates/nextjs-turbo-monorepo/base/packages/ui/tsconfig.json +12 -0
  298. package/templates/nextjs-turbo-monorepo/base/packages/ui/vitest.config.ts +28 -0
  299. package/templates/nextjs-turbo-monorepo/base/packages/utils/package.json +24 -0
  300. package/templates/nextjs-turbo-monorepo/base/packages/utils/src/date.ts +117 -0
  301. package/templates/nextjs-turbo-monorepo/base/packages/utils/src/index.ts +2 -0
  302. package/templates/nextjs-turbo-monorepo/base/packages/utils/src/string.ts +59 -0
  303. package/templates/nextjs-turbo-monorepo/base/packages/utils/tsconfig.json +9 -0
  304. package/templates/nextjs-turbo-monorepo/base/packages/utils/vitest.config.ts +13 -0
  305. package/templates/nextjs-turbo-monorepo/base/pnpm-workspace.yaml +3 -0
  306. package/templates/nextjs-turbo-monorepo/base/tsconfig.json +19 -0
  307. package/templates/nextjs-turbo-monorepo/base/turbo.json +47 -0
  308. package/templates/nextjs-turbo-monorepo/extras/boss-cli/assets/claude-md/template.md +0 -0
  309. package/templates/nextjs-turbo-monorepo/extras/boss-cli/assets/github-workflows/CODEOWNERS +0 -0
  310. package/templates/nextjs-turbo-monorepo/extras/boss-cli/assets/github-workflows/boss-ci.yml +139 -0
  311. package/templates/nextjs-turbo-monorepo/extras/boss-cli/assets/github-workflows/boss-gates.yml +116 -0
  312. package/templates/nextjs-turbo-monorepo/extras/config/kamal/_env +18 -0
  313. package/templates/nextjs-turbo-monorepo/extras/config/kamal/deploy.yml +92 -0
  314. package/templates/nextjs-turbo-monorepo/extras/scripts/deploy.sh +38 -0
  315. package/templates/nextjs-turbo-monorepo/extras/scripts/setup-db.sh +29 -0
  316. package/assets/claude-md/docs/container-use.md +0 -140
  317. package/dist/assets/claude-md/docs/container-use.md +0 -140
@@ -0,0 +1,745 @@
1
+ # Test-First Methodology
2
+
3
+ ## Description
4
+
5
+ Create, modify, and validate tests using Test-Driven Development (TDD) and Behavior-Driven Development (BDD). Use when implementing features, writing test suites, achieving coverage requirements, or ensuring code quality through test-first practices.
6
+
7
+ ## Overview
8
+
9
+ BOSS mandates Test-First development for all implementation work. This is NON-NEGOTIABLE per the constitution established by the architect. Every line of code must be preceded by a failing test.
10
+
11
+ **Core Principles**:
12
+ - **RED**: Write failing test first
13
+ - **GREEN**: Make test pass with minimal code
14
+ - **REFACTOR**: Clean up while keeping tests green
15
+ - **BDD**: Given/When/Then scenarios from spec.md become tests
16
+ - **Coverage**: Minimum 80% line, branch, and function coverage
17
+ - **Mutation**: Minimum 80% mutation score
18
+
19
+ ## TDD Cycle (RED-GREEN-REFACTOR)
20
+
21
+ ### Phase 1: RED (Write Failing Test)
22
+
23
+ ```typescript
24
+ // Step 1: Write test FIRST (before implementation exists)
25
+ import { describe, it, expect } from 'vitest';
26
+ import { registerUser } from './register'; // ← Doesn't exist yet!
27
+
28
+ describe('registerUser', () => {
29
+ it('creates user with valid email and password', async () => {
30
+ const result = await registerUser({
31
+ email: 'test@example.com',
32
+ password: 'SecurePass123',
33
+ });
34
+
35
+ expect(result.success).toBe(true);
36
+ expect(result.user.email).toBe('test@example.com');
37
+ expect(result.user.id).toBeDefined();
38
+ });
39
+ });
40
+
41
+ // Step 2: Run test → Should FAIL
42
+ // pnpm test src/auth/register.test.ts
43
+ // ❌ FAIL: Cannot find module './register'
44
+ ```
45
+
46
+ **Why RED First?**:
47
+ - Ensures test actually runs and can fail
48
+ - Validates test is testing the right thing
49
+ - Prevents false positives from tests that never fail
50
+
51
+ ### Phase 2: GREEN (Make Test Pass)
52
+
53
+ ```typescript
54
+ // src/auth/register.ts - Minimal implementation to pass
55
+ import { prisma } from '@repo/database';
56
+
57
+ export async function registerUser(data: { email: string; password: string }) {
58
+ const user = await prisma.user.create({
59
+ data: {
60
+ email: data.email,
61
+ password: await hashPassword(data.password),
62
+ },
63
+ });
64
+
65
+ return {
66
+ success: true,
67
+ user: {
68
+ id: user.id,
69
+ email: user.email,
70
+ },
71
+ };
72
+ }
73
+
74
+ // Step 3: Run test → Should PASS
75
+ // pnpm test src/auth/register.test.ts
76
+ // ✅ PASS: 1 test passed
77
+ ```
78
+
79
+ **Why Minimal Code?**:
80
+ - Avoid over-engineering
81
+ - Only write code that's needed to pass tests
82
+ - YAGNI (You Aren't Gonna Need It)
83
+
84
+ ### Phase 3: REFACTOR (Clean Up)
85
+
86
+ ```typescript
87
+ // Refactor while keeping tests green
88
+ export async function registerUser(data: RegisterInput) {
89
+ validateEmail(data.email); // Extract validation
90
+ const hashedPassword = await hashPassword(data.password);
91
+
92
+ const user = await createUserInDatabase({
93
+ email: data.email,
94
+ password: hashedPassword,
95
+ });
96
+
97
+ return formatUserResponse(user); // Extract formatting
98
+ }
99
+
100
+ // Step 4: Run test → Should STILL PASS
101
+ // pnpm test src/auth/register.test.ts
102
+ // ✅ PASS: 1 test passed (same result, cleaner code)
103
+ ```
104
+
105
+ **What to Refactor**:
106
+ - Extract duplicated code
107
+ - Improve naming
108
+ - Simplify complex logic
109
+ - Add type safety
110
+ - Optimize performance
111
+
112
+ **RED-GREEN-REFACTOR is mandatory for EVERY feature**
113
+
114
+ ## BDD: Given/When/Then
115
+
116
+ ### From Spec to Test
117
+
118
+ Spec-Kit specifications use BDD format - convert them directly to tests:
119
+
120
+ **spec.md (from spec-writer)**:
121
+ ```markdown
122
+ **Scenario 1.1: Successful Registration**
123
+ - **Given** I am on the registration page
124
+ - **And** I have a valid email "user@example.com"
125
+ - **And** I have a strong password "SecurePass123"
126
+ - **When** I submit the registration form
127
+ - **Then** I should see "Registration successful" message
128
+ - **And** I should receive a verification email
129
+ - **And** my account should be created in the database
130
+ ```
131
+
132
+ **Converted to Test**:
133
+ ```typescript
134
+ describe('User Registration', () => {
135
+ describe('Scenario 1.1: Successful Registration', () => {
136
+ it('shows success message, sends verification email, and creates account', async () => {
137
+ // GIVEN: Valid inputs
138
+ const email = 'user@example.com';
139
+ const password = 'SecurePass123';
140
+
141
+ // WHEN: Submit registration
142
+ const result = await registerUser({ email, password });
143
+
144
+ // THEN: Success message
145
+ expect(result.message).toBe('Registration successful');
146
+
147
+ // AND: Verification email sent
148
+ expect(emailService.sendVerification).toHaveBeenCalledWith(email);
149
+
150
+ // AND: Account created in database
151
+ const user = await prisma.user.findUnique({ where: { email } });
152
+ expect(user).toBeDefined();
153
+ expect(user.email).toBe(email);
154
+ });
155
+ });
156
+ });
157
+ ```
158
+
159
+ ### BDD Best Practices
160
+
161
+ ```typescript
162
+ // ✅ Good - descriptive test names match scenarios
163
+ describe('Scenario 1.2: Invalid Email Format', () => {
164
+ it('rejects registration and shows error message', async () => {
165
+ // ...
166
+ });
167
+ });
168
+
169
+ // ✅ Good - clear Given/When/Then structure
170
+ it('calculates total price with tax', () => {
171
+ // GIVEN
172
+ const items = [{ price: 100 }, { price: 200 }];
173
+ const taxRate = 0.1;
174
+
175
+ // WHEN
176
+ const total = calculateTotal(items, taxRate);
177
+
178
+ // THEN
179
+ expect(total).toBe(330); // (100 + 200) * 1.1
180
+ });
181
+
182
+ // ❌ Bad - unclear what's being tested
183
+ it('works correctly', () => {
184
+ const result = doSomething();
185
+ expect(result).toBeTruthy();
186
+ });
187
+
188
+ // ❌ Bad - testing multiple scenarios in one test
189
+ it('handles all cases', () => {
190
+ expect(func(1)).toBe(2);
191
+ expect(func(2)).toBe(4);
192
+ expect(func('invalid')).toThrow();
193
+ // Too many concerns!
194
+ });
195
+ ```
196
+
197
+ ## Test Pyramid
198
+
199
+ Maintain 70% unit / 20% integration / 10% E2E distribution:
200
+
201
+ ### Unit Tests (70%)
202
+
203
+ **Purpose**: Test individual functions/components in isolation.
204
+
205
+ ```typescript
206
+ // Unit test - fast, isolated
207
+ describe('calculateDiscount', () => {
208
+ it('applies 10% discount to regular users', () => {
209
+ expect(calculateDiscount(100, 'regular')).toBe(90);
210
+ });
211
+
212
+ it('applies 20% discount to premium users', () => {
213
+ expect(calculateDiscount(100, 'premium')).toBe(80);
214
+ });
215
+
216
+ it('throws error for negative amounts', () => {
217
+ expect(() => calculateDiscount(-10, 'regular')).toThrow('Amount must be positive');
218
+ });
219
+ });
220
+
221
+ // Mock dependencies
222
+ vi.mock('@repo/database', () => ({
223
+ prisma: {
224
+ user: {
225
+ findUnique: vi.fn(),
226
+ },
227
+ },
228
+ }));
229
+ ```
230
+
231
+ **Characteristics**:
232
+ - Fast (< 1ms each)
233
+ - No external dependencies (database, API, filesystem)
234
+ - Test pure logic
235
+ - Use mocks/stubs for dependencies
236
+
237
+ ### Integration Tests (20%)
238
+
239
+ **Purpose**: Test multiple components working together.
240
+
241
+ ```typescript
242
+ // Integration test - real database, real services
243
+ describe('User Registration Integration', () => {
244
+ beforeEach(async () => {
245
+ await prisma.user.deleteMany(); // Clean database
246
+ });
247
+
248
+ it('registers user and sends welcome email', async () => {
249
+ // Uses real Prisma, real email service
250
+ const result = await registerUser({
251
+ email: 'test@example.com',
252
+ password: 'SecurePass123',
253
+ });
254
+
255
+ // Verify database state
256
+ const user = await prisma.user.findUnique({
257
+ where: { email: 'test@example.com' },
258
+ });
259
+ expect(user).toBeDefined();
260
+
261
+ // Verify email was sent (integration with email service)
262
+ expect(emailService.sentEmails).toHaveLength(1);
263
+ expect(emailService.sentEmails[0].to).toBe('test@example.com');
264
+ });
265
+ });
266
+ ```
267
+
268
+ **Characteristics**:
269
+ - Slower (10-100ms each)
270
+ - Use real databases (test database, not production)
271
+ - Test multiple layers together
272
+ - Verify integrations between systems
273
+
274
+ ### E2E Tests (10%)
275
+
276
+ **Purpose**: Test complete user flows from UI to database.
277
+
278
+ ```typescript
279
+ // E2E test - real browser, real UI, real backend
280
+ import { test, expect } from '@playwright/test';
281
+
282
+ test('user can register and login', async ({ page }) => {
283
+ // Navigate to registration
284
+ await page.goto('/register');
285
+
286
+ // Fill form
287
+ await page.fill('input[name="email"]', 'test@example.com');
288
+ await page.fill('input[name="password"]', 'SecurePass123');
289
+ await page.click('button[type="submit"]');
290
+
291
+ // Verify success
292
+ await expect(page.locator('text=Registration successful')).toBeVisible();
293
+
294
+ // Navigate to login
295
+ await page.goto('/login');
296
+ await page.fill('input[name="email"]', 'test@example.com');
297
+ await page.fill('input[name="password"]', 'SecurePass123');
298
+ await page.click('button[type="submit"]');
299
+
300
+ // Verify redirect to dashboard
301
+ await expect(page).toHaveURL('/dashboard');
302
+ await expect(page.locator('text=Welcome')).toBeVisible();
303
+ });
304
+ ```
305
+
306
+ **Characteristics**:
307
+ - Slowest (1-10s each)
308
+ - Real browser interaction
309
+ - Test critical user journeys
310
+ - Catch issues that unit/integration tests miss
311
+
312
+ ## Coverage Requirements
313
+
314
+ ### Line/Branch/Function Coverage (≥80%)
315
+
316
+ ```bash
317
+ # Run tests with coverage
318
+ pnpm test:coverage
319
+
320
+ # Output:
321
+ # File | % Stmts | % Branch | % Funcs | % Lines |
322
+ # auth/ | 87.5 | 82.3 | 90.0 | 88.2 | ✅
323
+ # users/ | 92.1 | 88.7 | 95.0 | 91.5 | ✅
324
+ # payments/ | 76.4 | 71.2 | 80.0 | 75.8 | ❌ Below 80%
325
+ ```
326
+
327
+ **Meeting Coverage**:
328
+ ```typescript
329
+ // ❌ Low coverage - only happy path
330
+ test('processes payment', () => {
331
+ expect(processPayment(100)).resolves.toBe(true);
332
+ });
333
+ // Coverage: 50% (missing error cases, edge cases)
334
+
335
+ // ✅ High coverage - happy path + edge cases + errors
336
+ describe('processPayment', () => {
337
+ it('processes valid payment', async () => {
338
+ expect(await processPayment(100)).toBe(true);
339
+ });
340
+
341
+ it('rejects negative amounts', async () => {
342
+ await expect(processPayment(-10)).rejects.toThrow('Invalid amount');
343
+ });
344
+
345
+ it('rejects zero amount', async () => {
346
+ await expect(processPayment(0)).rejects.toThrow('Invalid amount');
347
+ });
348
+
349
+ it('handles payment gateway timeout', async () => {
350
+ vi.mocked(paymentGateway.process).mockRejectedValue(new TimeoutError());
351
+ await expect(processPayment(100)).rejects.toThrow('Payment timeout');
352
+ });
353
+ });
354
+ // Coverage: 95% (all branches tested)
355
+ ```
356
+
357
+ ### Mutation Testing (≥80%)
358
+
359
+ **Purpose**: Ensure tests actually catch bugs (not just execute code).
360
+
361
+ ```bash
362
+ # Run mutation testing
363
+ pnpm test:mutation
364
+
365
+ # Stryker mutates code and re-runs tests
366
+ # If tests still pass after mutation, tests are weak
367
+ ```
368
+
369
+ **Example**:
370
+ ```typescript
371
+ // Original code
372
+ function calculateDiscount(amount: number, userType: string) {
373
+ if (userType === 'premium') {
374
+ return amount * 0.8; // 20% discount
375
+ }
376
+ return amount * 0.9; // 10% discount
377
+ }
378
+
379
+ // Mutation 1: Change 0.8 to 0.9
380
+ // If test still passes → test doesn't verify actual discount amount!
381
+
382
+ // ❌ Weak test (mutation survives)
383
+ it('applies discount to premium users', () => {
384
+ const result = calculateDiscount(100, 'premium');
385
+ expect(result).toBeLessThan(100); // Too vague!
386
+ });
387
+
388
+ // ✅ Strong test (mutation killed)
389
+ it('applies 20% discount to premium users', () => {
390
+ const result = calculateDiscount(100, 'premium');
391
+ expect(result).toBe(80); // Exact value - catches mutation!
392
+ });
393
+ ```
394
+
395
+ ## Testing Patterns for BOSS Stack
396
+
397
+ ### Testing tRPC Routers
398
+
399
+ ```typescript
400
+ // src/server/api/routers/user.test.ts
401
+ import { appRouter } from '../root';
402
+ import { createInnerTRPCContext } from '../trpc';
403
+ import { prisma } from '@repo/database';
404
+
405
+ describe('user.list', () => {
406
+ it('returns all users', async () => {
407
+ // Setup
408
+ await prisma.user.createMany({
409
+ data: [
410
+ { email: 'user1@example.com', name: 'User 1' },
411
+ { email: 'user2@example.com', name: 'User 2' },
412
+ ],
413
+ });
414
+
415
+ // Create tRPC caller
416
+ const ctx = createInnerTRPCContext({});
417
+ const caller = appRouter.createCaller(ctx);
418
+
419
+ // Execute
420
+ const users = await caller.user.list();
421
+
422
+ // Verify
423
+ expect(users).toHaveLength(2);
424
+ expect(users[0].email).toBe('user1@example.com');
425
+ });
426
+ });
427
+ ```
428
+
429
+ ### Testing Server Components
430
+
431
+ ```typescript
432
+ // app/users/page.test.tsx
433
+ import { render } from '@testing-library/react';
434
+ import UsersPage from './page';
435
+
436
+ // Mock API call
437
+ vi.mock('@/lib/trpc/server', () => ({
438
+ api: {
439
+ user: {
440
+ list: vi.fn().mockResolvedValue([
441
+ { id: '1', name: 'User 1', email: 'user1@example.com' },
442
+ ]),
443
+ },
444
+ },
445
+ }));
446
+
447
+ test('renders user list', async () => {
448
+ const { findByText } = render(await UsersPage());
449
+
450
+ expect(await findByText('User 1')).toBeDefined();
451
+ expect(await findByText('user1@example.com')).toBeDefined();
452
+ });
453
+ ```
454
+
455
+ ### Testing Client Components
456
+
457
+ ```typescript
458
+ // components/UserForm.test.tsx
459
+ import { render, screen } from '@testing-library/react';
460
+ import { userEvent } from '@testing-library/user-event';
461
+ import { UserForm } from './UserForm';
462
+
463
+ test('submits form with valid data', async () => {
464
+ const onSubmit = vi.fn();
465
+ render(<UserForm onSubmit={onSubmit} />);
466
+
467
+ await userEvent.type(screen.getByLabelText('Name'), 'John Doe');
468
+ await userEvent.type(screen.getByLabelText('Email'), 'john@example.com');
469
+ await userEvent.click(screen.getByRole('button', { name: 'Submit' }));
470
+
471
+ expect(onSubmit).toHaveBeenCalledWith({
472
+ name: 'John Doe',
473
+ email: 'john@example.com',
474
+ });
475
+ });
476
+ ```
477
+
478
+ ### Testing Prisma Queries
479
+
480
+ ```typescript
481
+ // services/user.test.ts
482
+ import { prisma } from '@repo/database';
483
+ import { createUser, getUser } from './user';
484
+
485
+ describe('createUser', () => {
486
+ it('creates user in database', async () => {
487
+ const user = await createUser({
488
+ email: 'test@example.com',
489
+ name: 'Test User',
490
+ });
491
+
492
+ expect(user.id).toBeDefined();
493
+
494
+ // Verify in database
495
+ const dbUser = await prisma.user.findUnique({ where: { id: user.id } });
496
+ expect(dbUser).toBeDefined();
497
+ expect(dbUser.email).toBe('test@example.com');
498
+ });
499
+ });
500
+ ```
501
+
502
+ ## Test Organization
503
+
504
+ ### File Structure
505
+
506
+ ```
507
+ src/
508
+ ├── components/
509
+ │ ├── Button.tsx
510
+ │ └── Button.test.tsx # Co-located with component
511
+ ├── api/
512
+ │ ├── users.ts
513
+ │ └── users.test.ts # Co-located with API route
514
+ └── services/
515
+ ├── user.ts
516
+ └── user.test.ts # Co-located with service
517
+
518
+ tests/
519
+ ├── integration/
520
+ │ └── user-registration.test.ts # Integration tests
521
+ └── e2e/
522
+ └── auth-flow.spec.ts # Playwright E2E tests
523
+ ```
524
+
525
+ ### Test Naming
526
+
527
+ ```typescript
528
+ // ✅ Good - describes what and why
529
+ describe('UserService', () => {
530
+ describe('createUser', () => {
531
+ it('creates user with hashed password', () => {});
532
+ it('rejects duplicate email addresses', () => {});
533
+ it('sends welcome email after creation', () => {});
534
+ });
535
+ });
536
+
537
+ // ❌ Bad - vague names
538
+ describe('test user stuff', () => {
539
+ it('test1', () => {});
540
+ it('works', () => {});
541
+ });
542
+ ```
543
+
544
+ ## Common Patterns
545
+
546
+ ### Setup and Teardown
547
+
548
+ ```typescript
549
+ describe('User API', () => {
550
+ beforeEach(async () => {
551
+ // Clean database before each test
552
+ await prisma.user.deleteMany();
553
+ });
554
+
555
+ afterEach(async () => {
556
+ // Cleanup if needed
557
+ vi.clearAllMocks();
558
+ });
559
+
560
+ afterAll(async () => {
561
+ // Disconnect from database after all tests
562
+ await prisma.$disconnect();
563
+ });
564
+ });
565
+ ```
566
+
567
+ ### Test Fixtures
568
+
569
+ ```typescript
570
+ // tests/fixtures/users.ts
571
+ export const validUser = {
572
+ email: 'test@example.com',
573
+ name: 'Test User',
574
+ password: 'SecurePass123',
575
+ };
576
+
577
+ export const premiumUser = {
578
+ ...validUser,
579
+ tier: 'premium',
580
+ };
581
+
582
+ // In tests:
583
+ import { validUser } from '../fixtures/users';
584
+
585
+ test('creates user', async () => {
586
+ const user = await createUser(validUser);
587
+ expect(user.email).toBe(validUser.email);
588
+ });
589
+ ```
590
+
591
+ ### Mocking
592
+
593
+ ```typescript
594
+ // Mock external service
595
+ vi.mock('@/lib/email', () => ({
596
+ sendEmail: vi.fn().mockResolvedValue({ success: true }),
597
+ }));
598
+
599
+ // Mock Prisma
600
+ vi.mock('@repo/database', () => ({
601
+ prisma: {
602
+ user: {
603
+ create: vi.fn().mockResolvedValue({ id: '1', email: 'test@example.com' }),
604
+ findUnique: vi.fn(),
605
+ },
606
+ },
607
+ }));
608
+
609
+ // Verify mock was called
610
+ expect(sendEmail).toHaveBeenCalledWith({
611
+ to: 'test@example.com',
612
+ subject: 'Welcome',
613
+ });
614
+ ```
615
+
616
+ ## Anti-Patterns
617
+
618
+ ### ❌ Testing Implementation Details
619
+
620
+ ```typescript
621
+ // ❌ Bad - tests internal state
622
+ test('increments counter', () => {
623
+ const component = new Counter();
624
+ component.count = 5; // Testing private state
625
+ expect(component.count).toBe(5);
626
+ });
627
+
628
+ // ✅ Good - tests behavior
629
+ test('increments counter', async () => {
630
+ render(<Counter />);
631
+ await userEvent.click(screen.getByRole('button'));
632
+ expect(screen.getByText('Count: 1')).toBeDefined();
633
+ });
634
+ ```
635
+
636
+ ### ❌ Testing Third-Party Libraries
637
+
638
+ ```typescript
639
+ // ❌ Bad - testing Next.js router
640
+ test('Next.js router works', () => {
641
+ const router = useRouter();
642
+ router.push('/test');
643
+ expect(router.pathname).toBe('/test');
644
+ });
645
+
646
+ // ✅ Good - test YOUR code that uses router
647
+ test('navigates to dashboard on login', async () => {
648
+ const mockPush = vi.fn();
649
+ vi.mock('next/router', () => ({ useRouter: () => ({ push: mockPush }) }));
650
+
651
+ await userEvent.click(screen.getByRole('button', { name: 'Login' }));
652
+ expect(mockPush).toHaveBeenCalledWith('/dashboard');
653
+ });
654
+ ```
655
+
656
+ ### ❌ Skipping Edge Cases
657
+
658
+ ```typescript
659
+ // ❌ Bad - only happy path
660
+ test('adds numbers', () => {
661
+ expect(add(2, 3)).toBe(5);
662
+ });
663
+
664
+ // ✅ Good - edge cases covered
665
+ describe('add', () => {
666
+ it('adds positive numbers', () => {
667
+ expect(add(2, 3)).toBe(5);
668
+ });
669
+
670
+ it('adds negative numbers', () => {
671
+ expect(add(-2, -3)).toBe(-5);
672
+ });
673
+
674
+ it('adds zero', () => {
675
+ expect(add(0, 5)).toBe(5);
676
+ });
677
+
678
+ it('handles floating point', () => {
679
+ expect(add(0.1, 0.2)).toBeCloseTo(0.3);
680
+ });
681
+ });
682
+ ```
683
+
684
+ ## Workflow Integration
685
+
686
+ ### Developer Workflow
687
+
688
+ ```bash
689
+ # 1. Read spec.md scenario
690
+ cat .specify/specs/user-authentication/spec.md
691
+
692
+ # 2. Write FAILING test (RED)
693
+ cat > src/auth/register.test.ts << 'EOF'
694
+ test('registers user', () => {
695
+ expect(await registerUser({ ... })).toBeDefined();
696
+ });
697
+ EOF
698
+ pnpm test src/auth/register.test.ts
699
+ # ❌ FAIL: registerUser is not defined
700
+
701
+ # 3. Implement minimal code (GREEN)
702
+ cat > src/auth/register.ts << 'EOF'
703
+ export async function registerUser() { ... }
704
+ EOF
705
+ pnpm test src/auth/register.test.ts
706
+ # ✅ PASS
707
+
708
+ # 4. Refactor (keep GREEN)
709
+ # Clean up code, add edge cases, improve structure
710
+ pnpm test src/auth/register.test.ts
711
+ # ✅ PASS
712
+
713
+ # 5. Verify coverage
714
+ pnpm test:coverage
715
+ # Coverage: 87.5% ✅
716
+
717
+ # 6. Commit
718
+ git add src/auth/register.ts src/auth/register.test.ts
719
+ git commit -m "feat: implement user registration with TDD"
720
+ ```
721
+
722
+ ## When to Use This Skill
723
+
724
+ - Implementing any feature (TDD is mandatory)
725
+ - Converting BDD scenarios from spec.md to tests
726
+ - Achieving coverage requirements (≥80%)
727
+ - Writing mutation-resistant tests
728
+ - Organizing test suites
729
+ - Testing tRPC routers, Prisma queries, React components
730
+
731
+ ## Related Skills
732
+
733
+ - `nextjs-turbo-stack.md` - Testing with Vitest in the stack
734
+ - `spec-kit-workflow.md` - Converting spec.md to tests
735
+ - `boss-manifest-protocol.md` - Reporting test results
736
+
737
+ ## Key Takeaways
738
+
739
+ 1. **RED-GREEN-REFACTOR** - Mandatory cycle for ALL code
740
+ 2. **Test First, Always** - No code without a failing test
741
+ 3. **BDD Scenarios → Tests** - Direct conversion from spec.md
742
+ 4. **Test Pyramid** - 70% unit, 20% integration, 10% E2E
743
+ 5. **Coverage Minimums** - 80% line/branch/function, 80% mutation
744
+ 6. **Strong Assertions** - Exact values, not vague checks
745
+ 7. **Test Behavior** - Not implementation details