claude-code-pilot 2.0.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 (257) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/bin/install.js +431 -0
  4. package/docs/agent-guides/architecture.md +107 -0
  5. package/ecc/agents/architect.md +211 -0
  6. package/ecc/agents/code-reviewer.md +237 -0
  7. package/ecc/agents/doc-updater.md +107 -0
  8. package/ecc/agents/e2e-runner.md +107 -0
  9. package/ecc/agents/security-reviewer.md +108 -0
  10. package/ecc/agents/tdd-guide.md +91 -0
  11. package/ecc/commands/checkpoint.md +74 -0
  12. package/ecc/commands/evolve.md +178 -0
  13. package/ecc/commands/learn.md +70 -0
  14. package/ecc/commands/model-route.md +26 -0
  15. package/ecc/commands/quality-gate.md +29 -0
  16. package/ecc/commands/resume-session.md +155 -0
  17. package/ecc/commands/save-session.md +275 -0
  18. package/ecc/commands/sessions.md +305 -0
  19. package/ecc/commands/verify.md +59 -0
  20. package/ecc/contexts/dev.md +20 -0
  21. package/ecc/contexts/research.md +26 -0
  22. package/ecc/contexts/review.md +22 -0
  23. package/ecc/examples/CLAUDE.md +100 -0
  24. package/ecc/examples/django-api-CLAUDE.md +308 -0
  25. package/ecc/examples/go-microservice-CLAUDE.md +267 -0
  26. package/ecc/examples/rust-api-CLAUDE.md +285 -0
  27. package/ecc/examples/saas-nextjs-CLAUDE.md +166 -0
  28. package/ecc/examples/user-CLAUDE.md +109 -0
  29. package/ecc/rules/common/agents.md +49 -0
  30. package/ecc/rules/common/coding-style.md +48 -0
  31. package/ecc/rules/common/development-workflow.md +37 -0
  32. package/ecc/rules/common/git-workflow.md +24 -0
  33. package/ecc/rules/common/hooks.md +30 -0
  34. package/ecc/rules/common/patterns.md +31 -0
  35. package/ecc/rules/common/performance.md +55 -0
  36. package/ecc/rules/common/security.md +29 -0
  37. package/ecc/rules/common/testing.md +29 -0
  38. package/ecc/rules/golang/coding-style.md +32 -0
  39. package/ecc/rules/golang/hooks.md +17 -0
  40. package/ecc/rules/golang/patterns.md +45 -0
  41. package/ecc/rules/golang/security.md +34 -0
  42. package/ecc/rules/golang/testing.md +31 -0
  43. package/ecc/rules/kotlin/coding-style.md +86 -0
  44. package/ecc/rules/kotlin/patterns.md +146 -0
  45. package/ecc/rules/kotlin/security.md +82 -0
  46. package/ecc/rules/kotlin/testing.md +128 -0
  47. package/ecc/rules/perl/coding-style.md +46 -0
  48. package/ecc/rules/perl/hooks.md +22 -0
  49. package/ecc/rules/perl/patterns.md +76 -0
  50. package/ecc/rules/perl/security.md +69 -0
  51. package/ecc/rules/perl/testing.md +54 -0
  52. package/ecc/rules/php/coding-style.md +35 -0
  53. package/ecc/rules/php/hooks.md +24 -0
  54. package/ecc/rules/php/patterns.md +32 -0
  55. package/ecc/rules/php/security.md +33 -0
  56. package/ecc/rules/php/testing.md +34 -0
  57. package/ecc/rules/python/coding-style.md +42 -0
  58. package/ecc/rules/python/hooks.md +19 -0
  59. package/ecc/rules/python/patterns.md +39 -0
  60. package/ecc/rules/python/security.md +30 -0
  61. package/ecc/rules/python/testing.md +38 -0
  62. package/ecc/rules/swift/coding-style.md +47 -0
  63. package/ecc/rules/swift/hooks.md +20 -0
  64. package/ecc/rules/swift/patterns.md +66 -0
  65. package/ecc/rules/swift/security.md +33 -0
  66. package/ecc/rules/swift/testing.md +45 -0
  67. package/ecc/rules/typescript/coding-style.md +199 -0
  68. package/ecc/rules/typescript/hooks.md +22 -0
  69. package/ecc/rules/typescript/patterns.md +52 -0
  70. package/ecc/rules/typescript/security.md +28 -0
  71. package/ecc/rules/typescript/testing.md +18 -0
  72. package/ecc/scripts/hooks/check-hook-enabled.js +12 -0
  73. package/ecc/scripts/hooks/evaluate-session.js +100 -0
  74. package/ecc/scripts/hooks/pre-compact.js +48 -0
  75. package/ecc/scripts/hooks/run-with-flags-shell.sh +32 -0
  76. package/ecc/scripts/hooks/run-with-flags.js +120 -0
  77. package/ecc/scripts/hooks/session-end-marker.js +15 -0
  78. package/ecc/scripts/hooks/session-end.js +258 -0
  79. package/ecc/scripts/hooks/session-start.js +97 -0
  80. package/ecc/scripts/hooks/suggest-compact.js +80 -0
  81. package/ecc/scripts/lib/hook-flags.js +74 -0
  82. package/ecc/scripts/lib/package-manager.d.ts +119 -0
  83. package/ecc/scripts/lib/package-manager.js +431 -0
  84. package/ecc/scripts/lib/project-detect.js +428 -0
  85. package/ecc/scripts/lib/resolve-formatter.js +185 -0
  86. package/ecc/scripts/lib/session-aliases.d.ts +136 -0
  87. package/ecc/scripts/lib/session-aliases.js +481 -0
  88. package/ecc/scripts/lib/session-manager.d.ts +131 -0
  89. package/ecc/scripts/lib/session-manager.js +444 -0
  90. package/ecc/scripts/lib/shell-split.js +86 -0
  91. package/ecc/scripts/lib/utils.d.ts +183 -0
  92. package/ecc/scripts/lib/utils.js +543 -0
  93. package/ecc/skills/continuous-learning-v2/SKILL.md +365 -0
  94. package/ecc/skills/continuous-learning-v2/agents/observer-loop.sh +144 -0
  95. package/ecc/skills/continuous-learning-v2/agents/observer.md +198 -0
  96. package/ecc/skills/continuous-learning-v2/agents/start-observer.sh +194 -0
  97. package/ecc/skills/continuous-learning-v2/config.json +8 -0
  98. package/ecc/skills/continuous-learning-v2/hooks/observe.sh +246 -0
  99. package/ecc/skills/continuous-learning-v2/scripts/detect-project.sh +218 -0
  100. package/ecc/skills/continuous-learning-v2/scripts/instinct-cli.py +1148 -0
  101. package/ecc/skills/continuous-learning-v2/scripts/test_parse_instinct.py +984 -0
  102. package/ecc/skills/strategic-compact/SKILL.md +103 -0
  103. package/ecc/skills/strategic-compact/suggest-compact.sh +54 -0
  104. package/ecc/skills/verification-loop-SKILL.md +126 -0
  105. package/gsd/LICENSE +21 -0
  106. package/gsd/agents/gsd-codebase-mapper.md +772 -0
  107. package/gsd/agents/gsd-debugger.md +1257 -0
  108. package/gsd/agents/gsd-executor.md +489 -0
  109. package/gsd/agents/gsd-integration-checker.md +445 -0
  110. package/gsd/agents/gsd-nyquist-auditor.md +178 -0
  111. package/gsd/agents/gsd-phase-researcher.md +555 -0
  112. package/gsd/agents/gsd-plan-checker.md +708 -0
  113. package/gsd/agents/gsd-planner.md +1309 -0
  114. package/gsd/agents/gsd-project-researcher.md +631 -0
  115. package/gsd/agents/gsd-research-synthesizer.md +249 -0
  116. package/gsd/agents/gsd-roadmapper.md +652 -0
  117. package/gsd/agents/gsd-verifier.md +581 -0
  118. package/gsd/commands-gsd/add-phase.md +43 -0
  119. package/gsd/commands-gsd/add-tests.md +41 -0
  120. package/gsd/commands-gsd/add-todo.md +47 -0
  121. package/gsd/commands-gsd/audit-milestone.md +36 -0
  122. package/gsd/commands-gsd/check-todos.md +45 -0
  123. package/gsd/commands-gsd/cleanup.md +18 -0
  124. package/gsd/commands-gsd/complete-milestone.md +136 -0
  125. package/gsd/commands-gsd/debug.md +168 -0
  126. package/gsd/commands-gsd/discuss-phase.md +90 -0
  127. package/gsd/commands-gsd/execute-phase.md +41 -0
  128. package/gsd/commands-gsd/health.md +22 -0
  129. package/gsd/commands-gsd/help.md +22 -0
  130. package/gsd/commands-gsd/insert-phase.md +32 -0
  131. package/gsd/commands-gsd/join-discord.md +18 -0
  132. package/gsd/commands-gsd/list-phase-assumptions.md +46 -0
  133. package/gsd/commands-gsd/map-codebase.md +71 -0
  134. package/gsd/commands-gsd/new-milestone.md +44 -0
  135. package/gsd/commands-gsd/new-project.md +42 -0
  136. package/gsd/commands-gsd/pause-work.md +38 -0
  137. package/gsd/commands-gsd/plan-milestone-gaps.md +34 -0
  138. package/gsd/commands-gsd/plan-phase.md +45 -0
  139. package/gsd/commands-gsd/progress.md +24 -0
  140. package/gsd/commands-gsd/quick.md +45 -0
  141. package/gsd/commands-gsd/reapply-patches.md +123 -0
  142. package/gsd/commands-gsd/remove-phase.md +31 -0
  143. package/gsd/commands-gsd/research-phase.md +190 -0
  144. package/gsd/commands-gsd/resume-work.md +40 -0
  145. package/gsd/commands-gsd/set-profile.md +34 -0
  146. package/gsd/commands-gsd/settings.md +36 -0
  147. package/gsd/commands-gsd/update.md +37 -0
  148. package/gsd/commands-gsd/validate-phase.md +35 -0
  149. package/gsd/commands-gsd/verify-work.md +38 -0
  150. package/gsd/get-shit-done/bin/gsd-tools.cjs +592 -0
  151. package/gsd/get-shit-done/bin/lib/commands.cjs +548 -0
  152. package/gsd/get-shit-done/bin/lib/config.cjs +169 -0
  153. package/gsd/get-shit-done/bin/lib/core.cjs +492 -0
  154. package/gsd/get-shit-done/bin/lib/frontmatter.cjs +299 -0
  155. package/gsd/get-shit-done/bin/lib/init.cjs +710 -0
  156. package/gsd/get-shit-done/bin/lib/milestone.cjs +241 -0
  157. package/gsd/get-shit-done/bin/lib/phase.cjs +901 -0
  158. package/gsd/get-shit-done/bin/lib/roadmap.cjs +298 -0
  159. package/gsd/get-shit-done/bin/lib/state.cjs +721 -0
  160. package/gsd/get-shit-done/bin/lib/template.cjs +222 -0
  161. package/gsd/get-shit-done/bin/lib/verify.cjs +820 -0
  162. package/gsd/get-shit-done/references/checkpoints.md +776 -0
  163. package/gsd/get-shit-done/references/continuation-format.md +249 -0
  164. package/gsd/get-shit-done/references/decimal-phase-calculation.md +65 -0
  165. package/gsd/get-shit-done/references/git-integration.md +248 -0
  166. package/gsd/get-shit-done/references/git-planning-commit.md +38 -0
  167. package/gsd/get-shit-done/references/model-profile-resolution.md +34 -0
  168. package/gsd/get-shit-done/references/model-profiles.md +93 -0
  169. package/gsd/get-shit-done/references/phase-argument-parsing.md +61 -0
  170. package/gsd/get-shit-done/references/planning-config.md +200 -0
  171. package/gsd/get-shit-done/references/questioning.md +162 -0
  172. package/gsd/get-shit-done/references/tdd.md +263 -0
  173. package/gsd/get-shit-done/references/ui-brand.md +160 -0
  174. package/gsd/get-shit-done/references/verification-patterns.md +612 -0
  175. package/gsd/get-shit-done/templates/DEBUG.md +164 -0
  176. package/gsd/get-shit-done/templates/UAT.md +247 -0
  177. package/gsd/get-shit-done/templates/VALIDATION.md +76 -0
  178. package/gsd/get-shit-done/templates/codebase/architecture.md +255 -0
  179. package/gsd/get-shit-done/templates/codebase/concerns.md +310 -0
  180. package/gsd/get-shit-done/templates/codebase/conventions.md +307 -0
  181. package/gsd/get-shit-done/templates/codebase/integrations.md +280 -0
  182. package/gsd/get-shit-done/templates/codebase/stack.md +186 -0
  183. package/gsd/get-shit-done/templates/codebase/structure.md +285 -0
  184. package/gsd/get-shit-done/templates/codebase/testing.md +480 -0
  185. package/gsd/get-shit-done/templates/config.json +37 -0
  186. package/gsd/get-shit-done/templates/context.md +297 -0
  187. package/gsd/get-shit-done/templates/continue-here.md +78 -0
  188. package/gsd/get-shit-done/templates/debug-subagent-prompt.md +91 -0
  189. package/gsd/get-shit-done/templates/discovery.md +146 -0
  190. package/gsd/get-shit-done/templates/milestone-archive.md +123 -0
  191. package/gsd/get-shit-done/templates/milestone.md +115 -0
  192. package/gsd/get-shit-done/templates/phase-prompt.md +569 -0
  193. package/gsd/get-shit-done/templates/planner-subagent-prompt.md +117 -0
  194. package/gsd/get-shit-done/templates/project.md +184 -0
  195. package/gsd/get-shit-done/templates/requirements.md +231 -0
  196. package/gsd/get-shit-done/templates/research-project/ARCHITECTURE.md +204 -0
  197. package/gsd/get-shit-done/templates/research-project/FEATURES.md +147 -0
  198. package/gsd/get-shit-done/templates/research-project/PITFALLS.md +200 -0
  199. package/gsd/get-shit-done/templates/research-project/STACK.md +120 -0
  200. package/gsd/get-shit-done/templates/research-project/SUMMARY.md +170 -0
  201. package/gsd/get-shit-done/templates/research.md +552 -0
  202. package/gsd/get-shit-done/templates/retrospective.md +54 -0
  203. package/gsd/get-shit-done/templates/roadmap.md +202 -0
  204. package/gsd/get-shit-done/templates/state.md +176 -0
  205. package/gsd/get-shit-done/templates/summary-complex.md +59 -0
  206. package/gsd/get-shit-done/templates/summary-minimal.md +41 -0
  207. package/gsd/get-shit-done/templates/summary-standard.md +48 -0
  208. package/gsd/get-shit-done/templates/summary.md +248 -0
  209. package/gsd/get-shit-done/templates/user-setup.md +311 -0
  210. package/gsd/get-shit-done/templates/verification-report.md +322 -0
  211. package/gsd/get-shit-done/workflows/add-phase.md +112 -0
  212. package/gsd/get-shit-done/workflows/add-tests.md +351 -0
  213. package/gsd/get-shit-done/workflows/add-todo.md +158 -0
  214. package/gsd/get-shit-done/workflows/audit-milestone.md +332 -0
  215. package/gsd/get-shit-done/workflows/check-todos.md +177 -0
  216. package/gsd/get-shit-done/workflows/cleanup.md +152 -0
  217. package/gsd/get-shit-done/workflows/complete-milestone.md +764 -0
  218. package/gsd/get-shit-done/workflows/diagnose-issues.md +219 -0
  219. package/gsd/get-shit-done/workflows/discovery-phase.md +289 -0
  220. package/gsd/get-shit-done/workflows/discuss-phase.md +676 -0
  221. package/gsd/get-shit-done/workflows/execute-phase.md +459 -0
  222. package/gsd/get-shit-done/workflows/execute-plan.md +449 -0
  223. package/gsd/get-shit-done/workflows/health.md +159 -0
  224. package/gsd/get-shit-done/workflows/help.md +489 -0
  225. package/gsd/get-shit-done/workflows/insert-phase.md +130 -0
  226. package/gsd/get-shit-done/workflows/list-phase-assumptions.md +178 -0
  227. package/gsd/get-shit-done/workflows/map-codebase.md +316 -0
  228. package/gsd/get-shit-done/workflows/new-milestone.md +384 -0
  229. package/gsd/get-shit-done/workflows/new-project.md +1111 -0
  230. package/gsd/get-shit-done/workflows/pause-work.md +122 -0
  231. package/gsd/get-shit-done/workflows/plan-milestone-gaps.md +274 -0
  232. package/gsd/get-shit-done/workflows/plan-phase.md +560 -0
  233. package/gsd/get-shit-done/workflows/progress.md +382 -0
  234. package/gsd/get-shit-done/workflows/quick.md +601 -0
  235. package/gsd/get-shit-done/workflows/remove-phase.md +155 -0
  236. package/gsd/get-shit-done/workflows/research-phase.md +74 -0
  237. package/gsd/get-shit-done/workflows/resume-project.md +307 -0
  238. package/gsd/get-shit-done/workflows/set-profile.md +81 -0
  239. package/gsd/get-shit-done/workflows/settings.md +214 -0
  240. package/gsd/get-shit-done/workflows/transition.md +544 -0
  241. package/gsd/get-shit-done/workflows/update.md +240 -0
  242. package/gsd/get-shit-done/workflows/validate-phase.md +167 -0
  243. package/gsd/get-shit-done/workflows/verify-phase.md +243 -0
  244. package/gsd/get-shit-done/workflows/verify-work.md +583 -0
  245. package/gsd/hooks/gsd-check-update.js +81 -0
  246. package/gsd/hooks/gsd-context-monitor.js +141 -0
  247. package/gsd/hooks/gsd-statusline.js +115 -0
  248. package/kit/CLAUDE.md +43 -0
  249. package/kit/commands/kit/update.md +46 -0
  250. package/kit/commands/setup-refresh.md +50 -0
  251. package/kit/commands/setup.md +579 -0
  252. package/kit/commands/tool-guide.md +44 -0
  253. package/kit/hooks/kit-check-update.js +54 -0
  254. package/kit/mcp.json +10 -0
  255. package/kit/rules/code-style.md +24 -0
  256. package/manifest.json +30 -0
  257. package/package.json +36 -0
@@ -0,0 +1,308 @@
1
+ # Django REST API — Project CLAUDE.md
2
+
3
+ > Real-world example for a Django REST Framework API with PostgreSQL and Celery.
4
+ > Copy this to your project root and customize for your service.
5
+
6
+ ## Project Overview
7
+
8
+ **Stack:** Python 3.12+, Django 5.x, Django REST Framework, PostgreSQL, Celery + Redis, pytest, Docker Compose
9
+
10
+ **Architecture:** Domain-driven design with apps per business domain. DRF for API layer, Celery for async tasks, pytest for testing. All endpoints return JSON — no template rendering.
11
+
12
+ ## Critical Rules
13
+
14
+ ### Python Conventions
15
+
16
+ - Type hints on all function signatures — use `from __future__ import annotations`
17
+ - No `print()` statements — use `logging.getLogger(__name__)`
18
+ - f-strings for string formatting, never `%` or `.format()`
19
+ - Use `pathlib.Path` not `os.path` for file operations
20
+ - Imports sorted with isort: stdlib, third-party, local (enforced by ruff)
21
+
22
+ ### Database
23
+
24
+ - All queries use Django ORM — raw SQL only with `.raw()` and parameterized queries
25
+ - Migrations committed to git — never use `--fake` in production
26
+ - Use `select_related()` and `prefetch_related()` to prevent N+1 queries
27
+ - All models must have `created_at` and `updated_at` auto-fields
28
+ - Indexes on any field used in `filter()`, `order_by()`, or `WHERE` clauses
29
+
30
+ ```python
31
+ # BAD: N+1 query
32
+ orders = Order.objects.all()
33
+ for order in orders:
34
+ print(order.customer.name) # hits DB for each order
35
+
36
+ # GOOD: Single query with join
37
+ orders = Order.objects.select_related("customer").all()
38
+ ```
39
+
40
+ ### Authentication
41
+
42
+ - JWT via `djangorestframework-simplejwt` — access token (15 min) + refresh token (7 days)
43
+ - Permission classes on every view — never rely on default
44
+ - Use `IsAuthenticated` as base, add custom permissions for object-level access
45
+ - Token blacklisting enabled for logout
46
+
47
+ ### Serializers
48
+
49
+ - Use `ModelSerializer` for simple CRUD, `Serializer` for complex validation
50
+ - Separate read and write serializers when input/output shapes differ
51
+ - Validate at serializer level, not in views — views should be thin
52
+
53
+ ```python
54
+ class CreateOrderSerializer(serializers.Serializer):
55
+ product_id = serializers.UUIDField()
56
+ quantity = serializers.IntegerField(min_value=1, max_value=100)
57
+
58
+ def validate_product_id(self, value):
59
+ if not Product.objects.filter(id=value, active=True).exists():
60
+ raise serializers.ValidationError("Product not found or inactive")
61
+ return value
62
+
63
+ class OrderDetailSerializer(serializers.ModelSerializer):
64
+ customer = CustomerSerializer(read_only=True)
65
+ product = ProductSerializer(read_only=True)
66
+
67
+ class Meta:
68
+ model = Order
69
+ fields = ["id", "customer", "product", "quantity", "total", "status", "created_at"]
70
+ ```
71
+
72
+ ### Error Handling
73
+
74
+ - Use DRF exception handler for consistent error responses
75
+ - Custom exceptions for business logic in `core/exceptions.py`
76
+ - Never expose internal error details to clients
77
+
78
+ ```python
79
+ # core/exceptions.py
80
+ from rest_framework.exceptions import APIException
81
+
82
+ class InsufficientStockError(APIException):
83
+ status_code = 409
84
+ default_detail = "Insufficient stock for this order"
85
+ default_code = "insufficient_stock"
86
+ ```
87
+
88
+ ### Code Style
89
+
90
+ - No emojis in code or comments
91
+ - Max line length: 120 characters (enforced by ruff)
92
+ - Classes: PascalCase, functions/variables: snake_case, constants: UPPER_SNAKE_CASE
93
+ - Views are thin — business logic lives in service functions or model methods
94
+
95
+ ## File Structure
96
+
97
+ ```
98
+ config/
99
+ settings/
100
+ base.py # Shared settings
101
+ local.py # Dev overrides (DEBUG=True)
102
+ production.py # Production settings
103
+ urls.py # Root URL config
104
+ celery.py # Celery app configuration
105
+ apps/
106
+ accounts/ # User auth, registration, profile
107
+ models.py
108
+ serializers.py
109
+ views.py
110
+ services.py # Business logic
111
+ tests/
112
+ test_views.py
113
+ test_services.py
114
+ factories.py # Factory Boy factories
115
+ orders/ # Order management
116
+ models.py
117
+ serializers.py
118
+ views.py
119
+ services.py
120
+ tasks.py # Celery tasks
121
+ tests/
122
+ products/ # Product catalog
123
+ models.py
124
+ serializers.py
125
+ views.py
126
+ tests/
127
+ core/
128
+ exceptions.py # Custom API exceptions
129
+ permissions.py # Shared permission classes
130
+ pagination.py # Custom pagination
131
+ middleware.py # Request logging, timing
132
+ tests/
133
+ ```
134
+
135
+ ## Key Patterns
136
+
137
+ ### Service Layer
138
+
139
+ ```python
140
+ # apps/orders/services.py
141
+ from django.db import transaction
142
+
143
+ def create_order(*, customer, product_id: uuid.UUID, quantity: int) -> Order:
144
+ """Create an order with stock validation and payment hold."""
145
+ product = Product.objects.select_for_update().get(id=product_id)
146
+
147
+ if product.stock < quantity:
148
+ raise InsufficientStockError()
149
+
150
+ with transaction.atomic():
151
+ order = Order.objects.create(
152
+ customer=customer,
153
+ product=product,
154
+ quantity=quantity,
155
+ total=product.price * quantity,
156
+ )
157
+ product.stock -= quantity
158
+ product.save(update_fields=["stock", "updated_at"])
159
+
160
+ # Async: send confirmation email
161
+ send_order_confirmation.delay(order.id)
162
+ return order
163
+ ```
164
+
165
+ ### View Pattern
166
+
167
+ ```python
168
+ # apps/orders/views.py
169
+ class OrderViewSet(viewsets.ModelViewSet):
170
+ permission_classes = [IsAuthenticated]
171
+ pagination_class = StandardPagination
172
+
173
+ def get_serializer_class(self):
174
+ if self.action == "create":
175
+ return CreateOrderSerializer
176
+ return OrderDetailSerializer
177
+
178
+ def get_queryset(self):
179
+ return (
180
+ Order.objects
181
+ .filter(customer=self.request.user)
182
+ .select_related("product", "customer")
183
+ .order_by("-created_at")
184
+ )
185
+
186
+ def perform_create(self, serializer):
187
+ order = create_order(
188
+ customer=self.request.user,
189
+ product_id=serializer.validated_data["product_id"],
190
+ quantity=serializer.validated_data["quantity"],
191
+ )
192
+ serializer.instance = order
193
+ ```
194
+
195
+ ### Test Pattern (pytest + Factory Boy)
196
+
197
+ ```python
198
+ # apps/orders/tests/factories.py
199
+ import factory
200
+ from apps.accounts.tests.factories import UserFactory
201
+ from apps.products.tests.factories import ProductFactory
202
+
203
+ class OrderFactory(factory.django.DjangoModelFactory):
204
+ class Meta:
205
+ model = "orders.Order"
206
+
207
+ customer = factory.SubFactory(UserFactory)
208
+ product = factory.SubFactory(ProductFactory, stock=100)
209
+ quantity = 1
210
+ total = factory.LazyAttribute(lambda o: o.product.price * o.quantity)
211
+
212
+ # apps/orders/tests/test_views.py
213
+ import pytest
214
+ from rest_framework.test import APIClient
215
+
216
+ @pytest.mark.django_db
217
+ class TestCreateOrder:
218
+ def setup_method(self):
219
+ self.client = APIClient()
220
+ self.user = UserFactory()
221
+ self.client.force_authenticate(self.user)
222
+
223
+ def test_create_order_success(self):
224
+ product = ProductFactory(price=29_99, stock=10)
225
+ response = self.client.post("/api/orders/", {
226
+ "product_id": str(product.id),
227
+ "quantity": 2,
228
+ })
229
+ assert response.status_code == 201
230
+ assert response.data["total"] == 59_98
231
+
232
+ def test_create_order_insufficient_stock(self):
233
+ product = ProductFactory(stock=0)
234
+ response = self.client.post("/api/orders/", {
235
+ "product_id": str(product.id),
236
+ "quantity": 1,
237
+ })
238
+ assert response.status_code == 409
239
+
240
+ def test_create_order_unauthenticated(self):
241
+ self.client.force_authenticate(None)
242
+ response = self.client.post("/api/orders/", {})
243
+ assert response.status_code == 401
244
+ ```
245
+
246
+ ## Environment Variables
247
+
248
+ ```bash
249
+ # Django
250
+ SECRET_KEY=
251
+ DEBUG=False
252
+ ALLOWED_HOSTS=api.example.com
253
+
254
+ # Database
255
+ DATABASE_URL=postgres://user:pass@localhost:5432/myapp
256
+
257
+ # Redis (Celery broker + cache)
258
+ REDIS_URL=redis://localhost:6379/0
259
+
260
+ # JWT
261
+ JWT_ACCESS_TOKEN_LIFETIME=15 # minutes
262
+ JWT_REFRESH_TOKEN_LIFETIME=10080 # minutes (7 days)
263
+
264
+ # Email
265
+ EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
266
+ EMAIL_HOST=smtp.example.com
267
+ ```
268
+
269
+ ## Testing Strategy
270
+
271
+ ```bash
272
+ # Run all tests
273
+ pytest --cov=apps --cov-report=term-missing
274
+
275
+ # Run specific app tests
276
+ pytest apps/orders/tests/ -v
277
+
278
+ # Run with parallel execution
279
+ pytest -n auto
280
+
281
+ # Only failing tests from last run
282
+ pytest --lf
283
+ ```
284
+
285
+ ## ECC Workflow
286
+
287
+ ```bash
288
+ # Planning
289
+ /plan "Add order refund system with Stripe integration"
290
+
291
+ # Development with TDD
292
+ /tdd # pytest-based TDD workflow
293
+
294
+ # Review
295
+ /python-review # Python-specific code review
296
+ /security-scan # Django security audit
297
+ /code-review # General quality check
298
+
299
+ # Verification
300
+ /verify # Build, lint, test, security scan
301
+ ```
302
+
303
+ ## Git Workflow
304
+
305
+ - `feat:` new features, `fix:` bug fixes, `refactor:` code changes
306
+ - Feature branches from `main`, PRs required
307
+ - CI: ruff (lint + format), mypy (types), pytest (tests), safety (dep check)
308
+ - Deploy: Docker image, managed via Kubernetes or Railway
@@ -0,0 +1,267 @@
1
+ # Go Microservice — Project CLAUDE.md
2
+
3
+ > Real-world example for a Go microservice with PostgreSQL, gRPC, and Docker.
4
+ > Copy this to your project root and customize for your service.
5
+
6
+ ## Project Overview
7
+
8
+ **Stack:** Go 1.22+, PostgreSQL, gRPC + REST (grpc-gateway), Docker, sqlc (type-safe SQL), Wire (dependency injection)
9
+
10
+ **Architecture:** Clean architecture with domain, repository, service, and handler layers. gRPC as primary transport with REST gateway for external clients.
11
+
12
+ ## Critical Rules
13
+
14
+ ### Go Conventions
15
+
16
+ - Follow Effective Go and the Go Code Review Comments guide
17
+ - Use `errors.New` / `fmt.Errorf` with `%w` for wrapping — never string matching on errors
18
+ - No `init()` functions — explicit initialization in `main()` or constructors
19
+ - No global mutable state — pass dependencies via constructors
20
+ - Context must be the first parameter and propagated through all layers
21
+
22
+ ### Database
23
+
24
+ - All queries in `queries/` as plain SQL — sqlc generates type-safe Go code
25
+ - Migrations in `migrations/` using golang-migrate — never alter the database directly
26
+ - Use transactions for multi-step operations via `pgx.Tx`
27
+ - All queries must use parameterized placeholders (`$1`, `$2`) — never string formatting
28
+
29
+ ### Error Handling
30
+
31
+ - Return errors, don't panic — panics are only for truly unrecoverable situations
32
+ - Wrap errors with context: `fmt.Errorf("creating user: %w", err)`
33
+ - Define sentinel errors in `domain/errors.go` for business logic
34
+ - Map domain errors to gRPC status codes in the handler layer
35
+
36
+ ```go
37
+ // Domain layer — sentinel errors
38
+ var (
39
+ ErrUserNotFound = errors.New("user not found")
40
+ ErrEmailTaken = errors.New("email already registered")
41
+ )
42
+
43
+ // Handler layer — map to gRPC status
44
+ func toGRPCError(err error) error {
45
+ switch {
46
+ case errors.Is(err, domain.ErrUserNotFound):
47
+ return status.Error(codes.NotFound, err.Error())
48
+ case errors.Is(err, domain.ErrEmailTaken):
49
+ return status.Error(codes.AlreadyExists, err.Error())
50
+ default:
51
+ return status.Error(codes.Internal, "internal error")
52
+ }
53
+ }
54
+ ```
55
+
56
+ ### Code Style
57
+
58
+ - No emojis in code or comments
59
+ - Exported types and functions must have doc comments
60
+ - Keep functions under 50 lines — extract helpers
61
+ - Use table-driven tests for all logic with multiple cases
62
+ - Prefer `struct{}` for signal channels, not `bool`
63
+
64
+ ## File Structure
65
+
66
+ ```
67
+ cmd/
68
+ server/
69
+ main.go # Entrypoint, Wire injection, graceful shutdown
70
+ internal/
71
+ domain/ # Business types and interfaces
72
+ user.go # User entity and repository interface
73
+ errors.go # Sentinel errors
74
+ service/ # Business logic
75
+ user_service.go
76
+ user_service_test.go
77
+ repository/ # Data access (sqlc-generated + custom)
78
+ postgres/
79
+ user_repo.go
80
+ user_repo_test.go # Integration tests with testcontainers
81
+ handler/ # gRPC + REST handlers
82
+ grpc/
83
+ user_handler.go
84
+ rest/
85
+ user_handler.go
86
+ config/ # Configuration loading
87
+ config.go
88
+ proto/ # Protobuf definitions
89
+ user/v1/
90
+ user.proto
91
+ queries/ # SQL queries for sqlc
92
+ user.sql
93
+ migrations/ # Database migrations
94
+ 001_create_users.up.sql
95
+ 001_create_users.down.sql
96
+ ```
97
+
98
+ ## Key Patterns
99
+
100
+ ### Repository Interface
101
+
102
+ ```go
103
+ type UserRepository interface {
104
+ Create(ctx context.Context, user *User) error
105
+ FindByID(ctx context.Context, id uuid.UUID) (*User, error)
106
+ FindByEmail(ctx context.Context, email string) (*User, error)
107
+ Update(ctx context.Context, user *User) error
108
+ Delete(ctx context.Context, id uuid.UUID) error
109
+ }
110
+ ```
111
+
112
+ ### Service with Dependency Injection
113
+
114
+ ```go
115
+ type UserService struct {
116
+ repo domain.UserRepository
117
+ hasher PasswordHasher
118
+ logger *slog.Logger
119
+ }
120
+
121
+ func NewUserService(repo domain.UserRepository, hasher PasswordHasher, logger *slog.Logger) *UserService {
122
+ return &UserService{repo: repo, hasher: hasher, logger: logger}
123
+ }
124
+
125
+ func (s *UserService) Create(ctx context.Context, req CreateUserRequest) (*domain.User, error) {
126
+ existing, err := s.repo.FindByEmail(ctx, req.Email)
127
+ if err != nil && !errors.Is(err, domain.ErrUserNotFound) {
128
+ return nil, fmt.Errorf("checking email: %w", err)
129
+ }
130
+ if existing != nil {
131
+ return nil, domain.ErrEmailTaken
132
+ }
133
+
134
+ hashed, err := s.hasher.Hash(req.Password)
135
+ if err != nil {
136
+ return nil, fmt.Errorf("hashing password: %w", err)
137
+ }
138
+
139
+ user := &domain.User{
140
+ ID: uuid.New(),
141
+ Name: req.Name,
142
+ Email: req.Email,
143
+ Password: hashed,
144
+ }
145
+ if err := s.repo.Create(ctx, user); err != nil {
146
+ return nil, fmt.Errorf("creating user: %w", err)
147
+ }
148
+ return user, nil
149
+ }
150
+ ```
151
+
152
+ ### Table-Driven Tests
153
+
154
+ ```go
155
+ func TestUserService_Create(t *testing.T) {
156
+ tests := []struct {
157
+ name string
158
+ req CreateUserRequest
159
+ setup func(*MockUserRepo)
160
+ wantErr error
161
+ }{
162
+ {
163
+ name: "valid user",
164
+ req: CreateUserRequest{Name: "Alice", Email: "alice@example.com", Password: "secure123"},
165
+ setup: func(m *MockUserRepo) {
166
+ m.On("FindByEmail", mock.Anything, "alice@example.com").Return(nil, domain.ErrUserNotFound)
167
+ m.On("Create", mock.Anything, mock.Anything).Return(nil)
168
+ },
169
+ wantErr: nil,
170
+ },
171
+ {
172
+ name: "duplicate email",
173
+ req: CreateUserRequest{Name: "Alice", Email: "taken@example.com", Password: "secure123"},
174
+ setup: func(m *MockUserRepo) {
175
+ m.On("FindByEmail", mock.Anything, "taken@example.com").Return(&domain.User{}, nil)
176
+ },
177
+ wantErr: domain.ErrEmailTaken,
178
+ },
179
+ }
180
+
181
+ for _, tt := range tests {
182
+ t.Run(tt.name, func(t *testing.T) {
183
+ repo := new(MockUserRepo)
184
+ tt.setup(repo)
185
+ svc := NewUserService(repo, &bcryptHasher{}, slog.Default())
186
+
187
+ _, err := svc.Create(context.Background(), tt.req)
188
+
189
+ if tt.wantErr != nil {
190
+ assert.ErrorIs(t, err, tt.wantErr)
191
+ } else {
192
+ assert.NoError(t, err)
193
+ }
194
+ })
195
+ }
196
+ }
197
+ ```
198
+
199
+ ## Environment Variables
200
+
201
+ ```bash
202
+ # Database
203
+ DATABASE_URL=postgres://user:pass@localhost:5432/myservice?sslmode=disable
204
+
205
+ # gRPC
206
+ GRPC_PORT=50051
207
+ REST_PORT=8080
208
+
209
+ # Auth
210
+ JWT_SECRET= # Load from vault in production
211
+ TOKEN_EXPIRY=24h
212
+
213
+ # Observability
214
+ LOG_LEVEL=info # debug, info, warn, error
215
+ OTEL_ENDPOINT= # OpenTelemetry collector
216
+ ```
217
+
218
+ ## Testing Strategy
219
+
220
+ ```bash
221
+ /go-test # TDD workflow for Go
222
+ /go-review # Go-specific code review
223
+ /go-build # Fix build errors
224
+ ```
225
+
226
+ ### Test Commands
227
+
228
+ ```bash
229
+ # Unit tests (fast, no external deps)
230
+ go test ./internal/... -short -count=1
231
+
232
+ # Integration tests (requires Docker for testcontainers)
233
+ go test ./internal/repository/... -count=1 -timeout 120s
234
+
235
+ # All tests with coverage
236
+ go test ./... -coverprofile=coverage.out -count=1
237
+ go tool cover -func=coverage.out # summary
238
+ go tool cover -html=coverage.out # browser
239
+
240
+ # Race detector
241
+ go test ./... -race -count=1
242
+ ```
243
+
244
+ ## ECC Workflow
245
+
246
+ ```bash
247
+ # Planning
248
+ /plan "Add rate limiting to user endpoints"
249
+
250
+ # Development
251
+ /go-test # TDD with Go-specific patterns
252
+
253
+ # Review
254
+ /go-review # Go idioms, error handling, concurrency
255
+ /security-scan # Secrets and vulnerabilities
256
+
257
+ # Before merge
258
+ go vet ./...
259
+ staticcheck ./...
260
+ ```
261
+
262
+ ## Git Workflow
263
+
264
+ - `feat:` new features, `fix:` bug fixes, `refactor:` code changes
265
+ - Feature branches from `main`, PRs required
266
+ - CI: `go vet`, `staticcheck`, `go test -race`, `golangci-lint`
267
+ - Deploy: Docker image built in CI, deployed to Kubernetes