cc-codeconductor 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +319 -0
  3. package/dist/index.js +12741 -0
  4. package/package.json +51 -0
  5. package/policy.yml +124 -0
  6. package/presets/claude/CLAUDE.md +598 -0
  7. package/presets/claude/commands/cc/feature.md +115 -0
  8. package/presets/claude/commands/cc/fix.md +121 -0
  9. package/presets/claude/commands/cc/refactor.md +148 -0
  10. package/presets/claude/commands/cc/review.md +126 -0
  11. package/presets/claude/commands/cc/tdd-cycle.md +226 -0
  12. package/presets/claude/commands/cc/test-plan.md +138 -0
  13. package/presets/claude/settings.json +37 -0
  14. package/presets/claude/skills/api-versioning/SKILL.md +389 -0
  15. package/presets/claude/skills/django-orm/SKILL.md +455 -0
  16. package/presets/claude/skills/django-testing/SKILL.md +409 -0
  17. package/presets/claude/skills/jpa-postgres/SKILL.md +618 -0
  18. package/presets/claude/skills/python/SKILL.md +606 -0
  19. package/presets/claude/skills/python-django-stack/SKILL.md +492 -0
  20. package/presets/claude/skills/python-fastapi-stack/SKILL.md +457 -0
  21. package/presets/claude/skills/spring-boot-feature/SKILL.md +558 -0
  22. package/presets/claude/skills/spring-boot-kotlin/SKILL.md +400 -0
  23. package/presets/claude/skills/sqlalchemy/SKILL.md +466 -0
  24. package/presets/claude/skills/testing-strategy/SKILL.md +479 -0
  25. package/presets/codex/AGENTS.md +883 -0
  26. package/presets/codex/README.md +102 -0
  27. package/presets/codex/skills/api-versioning/SKILL.md +389 -0
  28. package/presets/codex/skills/django-orm/SKILL.md +455 -0
  29. package/presets/codex/skills/django-testing/SKILL.md +409 -0
  30. package/presets/codex/skills/jpa-postgres/SKILL.md +618 -0
  31. package/presets/codex/skills/python/SKILL.md +606 -0
  32. package/presets/codex/skills/python-django-stack/SKILL.md +492 -0
  33. package/presets/codex/skills/python-fastapi-stack/SKILL.md +457 -0
  34. package/presets/codex/skills/spring-boot-feature/SKILL.md +558 -0
  35. package/presets/codex/skills/spring-boot-kotlin/SKILL.md +400 -0
  36. package/presets/codex/skills/sqlalchemy/SKILL.md +466 -0
  37. package/presets/codex/skills/testing-strategy/SKILL.md +479 -0
  38. package/presets/opencode/README.md +191 -0
  39. package/presets/opencode/agents/architect.md +133 -0
  40. package/presets/opencode/agents/docs.md +113 -0
  41. package/presets/opencode/agents/implementer.md +116 -0
  42. package/presets/opencode/agents/orchestrator.md +248 -0
  43. package/presets/opencode/agents/repo-explorer.md +119 -0
  44. package/presets/opencode/agents/reviewer.md +130 -0
  45. package/presets/opencode/agents/task-coach.md +103 -0
  46. package/presets/opencode/agents/tester.md +269 -0
  47. package/presets/opencode/commands/cc-feature.md +114 -0
  48. package/presets/opencode/commands/cc-fix.md +123 -0
  49. package/presets/opencode/commands/cc-refactor.md +148 -0
  50. package/presets/opencode/commands/cc-review.md +141 -0
  51. package/presets/opencode/commands/cc-tdd-cycle.md +225 -0
  52. package/presets/opencode/commands/cc-test-plan.md +144 -0
  53. package/presets/opencode/opencode.jsonc +89 -0
  54. package/presets/opencode/prompts/v0.1.0/architect.md +213 -0
  55. package/presets/opencode/prompts/v0.1.0/docs.md +181 -0
  56. package/presets/opencode/prompts/v0.1.0/implementer.md +154 -0
  57. package/presets/opencode/prompts/v0.1.0/orchestrator.md +169 -0
  58. package/presets/opencode/prompts/v0.1.0/repo-explorer.md +102 -0
  59. package/presets/opencode/prompts/v0.1.0/reviewer.md +183 -0
  60. package/presets/opencode/prompts/v0.1.0/task-coach.md +142 -0
  61. package/presets/opencode/prompts/v0.1.0/tester.md +160 -0
  62. package/presets/opencode/prompts/v0.2.0/architect.md +219 -0
  63. package/presets/opencode/prompts/v0.2.0/docs.md +187 -0
  64. package/presets/opencode/prompts/v0.2.0/implementer.md +160 -0
  65. package/presets/opencode/prompts/v0.2.0/orchestrator.md +238 -0
  66. package/presets/opencode/prompts/v0.2.0/repo-explorer.md +108 -0
  67. package/presets/opencode/prompts/v0.2.0/reviewer.md +190 -0
  68. package/presets/opencode/prompts/v0.2.0/task-coach.md +153 -0
  69. package/presets/opencode/prompts/v0.2.0/tester.md +249 -0
  70. package/presets/opencode/skills/api-versioning/SKILL.md +388 -0
  71. package/presets/opencode/skills/astro/SKILL.md +313 -0
  72. package/presets/opencode/skills/code-review/SKILL.md +202 -0
  73. package/presets/opencode/skills/django-orm/SKILL.md +455 -0
  74. package/presets/opencode/skills/django-testing/SKILL.md +408 -0
  75. package/presets/opencode/skills/django-uv/SKILL.md +400 -0
  76. package/presets/opencode/skills/jpa-postgres/SKILL.md +617 -0
  77. package/presets/opencode/skills/nextjs-typescript/SKILL.md +385 -0
  78. package/presets/opencode/skills/python/SKILL.md +605 -0
  79. package/presets/opencode/skills/python-django-stack/SKILL.md +491 -0
  80. package/presets/opencode/skills/python-fastapi-stack/SKILL.md +456 -0
  81. package/presets/opencode/skills/security/SKILL.md +376 -0
  82. package/presets/opencode/skills/spring-boot-feature/SKILL.md +557 -0
  83. package/presets/opencode/skills/spring-boot-kotlin/SKILL.md +399 -0
  84. package/presets/opencode/skills/spring-boot-testing-strategy/SKILL.md +470 -0
  85. package/presets/opencode/skills/sqlalchemy/SKILL.md +465 -0
  86. package/presets/opencode/skills/testing-tdd/SKILL.md +586 -0
  87. package/src/presets/council/council.yml +59 -0
  88. package/src/presets/manifests/claude.yml +23 -0
  89. package/src/presets/manifests/codex.yml +12 -0
  90. package/src/presets/manifests/opencode.yml +18 -0
  91. package/src/presets/models/claude.yml +37 -0
  92. package/src/presets/models/codex.yml +38 -0
  93. package/src/presets/models/opencode.yml +37 -0
@@ -0,0 +1,400 @@
1
+ ---
2
+ id: django-uv
3
+ version: 1.0.0
4
+ name: Django + UV
5
+ description: >
6
+ Provides expert knowledge for building Django 5+ projects with UV as the package manager, domain-driven app structure, ruff for linting, and pytest-django for testing.
7
+
8
+ compatibility:
9
+ tools: [claude, codex, opencode]
10
+ stacks:
11
+ languages: []
12
+ frameworks: []
13
+
14
+ risk:
15
+ level: medium
16
+ can_execute_shell: false
17
+ can_modify_files: true
18
+ requires_network: false
19
+
20
+ inputs: []
21
+
22
+ outputs: []
23
+
24
+ quality:
25
+ reviewed_by: codeconductor-core
26
+ version: 0.1.0
27
+ ---
28
+
29
+
30
+
31
+ # Django + UV
32
+
33
+ ## Project Setup with UV
34
+
35
+ UV replaces pip, pip-tools, virtualenv, and pyenv in a single binary. Always
36
+ use UV for dependency management.
37
+
38
+ ```bash
39
+ # Create project
40
+ uv init my-project
41
+ cd my-project
42
+
43
+ # Add Django and dependencies
44
+ uv add django psycopg[binary] djangorestframework django-environ
45
+
46
+ # Add dev dependencies
47
+ uv add --dev pytest pytest-django ruff factory-boy coverage
48
+
49
+ # Run management commands
50
+ uv run python manage.py migrate
51
+ uv run python manage.py runserver
52
+ ```
53
+
54
+ ### pyproject.toml Layout
55
+
56
+ ```toml
57
+ [project]
58
+ name = "my-project"
59
+ version = "0.1.0"
60
+ requires-python = ">=3.12"
61
+ dependencies = [
62
+ "django>=5.0",
63
+ "psycopg[binary]>=3.1",
64
+ "djangorestframework>=3.15",
65
+ "django-environ>=0.11",
66
+ ]
67
+
68
+ [project.optional-dependencies]
69
+ dev = [
70
+ "pytest>=8.0",
71
+ "pytest-django>=4.8",
72
+ "ruff>=0.4",
73
+ "factory-boy>=3.3",
74
+ "coverage>=7.4",
75
+ ]
76
+
77
+ [tool.ruff]
78
+ line-length = 88
79
+ target-version = "py312"
80
+
81
+ [tool.ruff.lint]
82
+ select = ["E", "F", "I", "N", "UP", "B", "SIM"]
83
+ ignore = ["E501"]
84
+
85
+ [tool.pytest.ini_options]
86
+ DJANGO_SETTINGS_MODULE = "config.settings.test"
87
+ python_files = ["test_*.py", "*_test.py"]
88
+ python_classes = ["Test*"]
89
+ python_functions = ["test_*"]
90
+
91
+ [tool.coverage.run]
92
+ source = ["."]
93
+ omit = ["*/migrations/*", "*/tests/*", "manage.py"]
94
+ ```
95
+
96
+ ## App Structure (Domain-Driven)
97
+
98
+ Organize by domain, not by technical layer. Each Django app owns its domain
99
+ entirely.
100
+
101
+ ```text
102
+ my_project/
103
+ config/
104
+ settings/
105
+ base.py — shared settings
106
+ dev.py — local overrides
107
+ test.py — test-specific settings
108
+ prod.py — production settings
109
+ urls.py
110
+ wsgi.py
111
+ apps/
112
+ users/
113
+ models.py
114
+ services.py — business logic, never in views
115
+ views.py — thin; delegates to services
116
+ serializers.py
117
+ admin.py
118
+ urls.py
119
+ tests/
120
+ test_models.py
121
+ test_services.py
122
+ test_views.py
123
+ factories.py
124
+ orders/
125
+ ...
126
+ manage.py
127
+ pyproject.toml
128
+ ```
129
+
130
+ ## Settings Split
131
+
132
+ ```python
133
+ # config/settings/base.py
134
+ from pathlib import Path
135
+ import environ
136
+
137
+ env = environ.Env()
138
+ BASE_DIR = Path(__file__).resolve().parent.parent.parent
139
+
140
+ SECRET_KEY = env("SECRET_KEY")
141
+ DEBUG = env.bool("DEBUG", default=False)
142
+
143
+ INSTALLED_APPS = [
144
+ "django.contrib.admin",
145
+ "django.contrib.auth",
146
+ "django.contrib.contenttypes",
147
+ "rest_framework",
148
+ "apps.users",
149
+ "apps.orders",
150
+ ]
151
+
152
+ DATABASES = {
153
+ "default": env.db("DATABASE_URL")
154
+ }
155
+ ```
156
+
157
+ ```python
158
+ # config/settings/test.py
159
+ from .base import * # noqa: F403
160
+
161
+ DATABASES = {
162
+ "default": {
163
+ "ENGINE": "django.db.backends.sqlite3",
164
+ "NAME": ":memory:",
165
+ }
166
+ }
167
+
168
+ # Never send real emails in tests
169
+ EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
170
+ ```
171
+
172
+ ## Models
173
+
174
+ ```python
175
+ # apps/users/models.py
176
+ import uuid
177
+ from django.db import models
178
+ from django.contrib.auth.models import AbstractUser
179
+
180
+
181
+ class User(AbstractUser):
182
+ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
183
+ email = models.EmailField(unique=True)
184
+ bio = models.TextField(blank=True)
185
+ created_at = models.DateTimeField(auto_now_add=True)
186
+ updated_at = models.DateTimeField(auto_now=True)
187
+
188
+ USERNAME_FIELD = "email"
189
+ REQUIRED_FIELDS = ["username"]
190
+
191
+ class Meta:
192
+ ordering = ["-created_at"]
193
+
194
+ def __str__(self) -> str:
195
+ return self.email
196
+ ```
197
+
198
+ Rules:
199
+
200
+ - Use UUID primary keys — never expose sequential integer IDs in public APIs
201
+ - `auto_now_add` and `auto_now` for timestamps — never set manually
202
+ - Always define `__str__` — it appears in admin and error messages
203
+ - Use `blank=True` for optional strings (form validation), `null=True` only for
204
+ nullable FK/non-string fields
205
+
206
+ ## Service Layer
207
+
208
+ Business logic lives in `services.py`. Views are thin HTTP adapters.
209
+
210
+ ```python
211
+ # apps/users/services.py
212
+ from django.db import transaction
213
+ from django.contrib.auth.hashers import make_password
214
+ from .models import User
215
+
216
+
217
+ class UserService:
218
+
219
+ @staticmethod
220
+ def create_user(*, email: str, password: str, username: str) -> User:
221
+ if User.objects.filter(email=email).exists():
222
+ raise ValueError(f"Email {email!r} is already registered")
223
+
224
+ with transaction.atomic():
225
+ user = User.objects.create(
226
+ email=email,
227
+ username=username,
228
+ password=make_password(password),
229
+ )
230
+ return user
231
+
232
+ @staticmethod
233
+ def deactivate_user(*, user_id: str) -> User:
234
+ user = User.objects.get(id=user_id)
235
+ user.is_active = False
236
+ user.save(update_fields=["is_active", "updated_at"])
237
+ return user
238
+ ```
239
+
240
+ Rules:
241
+
242
+ - Use keyword-only arguments (`*` separator) in service methods — prevents
243
+ positional argument confusion
244
+ - Use `update_fields` in `save()` — avoids overwriting unintended fields and
245
+ reduces the UPDATE query scope
246
+ - Wrap multi-step writes in `transaction.atomic()`
247
+ - Never import from `views.py` in `services.py` — keep the dependency direction
248
+ strict: views → services → models
249
+
250
+ ## Views (DRF)
251
+
252
+ ```python
253
+ # apps/users/views.py
254
+ from rest_framework import status
255
+ from rest_framework.decorators import api_view, permission_classes
256
+ from rest_framework.permissions import IsAuthenticated
257
+ from rest_framework.request import Request
258
+ from rest_framework.response import Response
259
+
260
+ from .serializers import CreateUserSerializer, UserSerializer
261
+ from .services import UserService
262
+
263
+
264
+ @api_view(["POST"])
265
+ def create_user(request: Request) -> Response:
266
+ serializer = CreateUserSerializer(data=request.data)
267
+ serializer.is_valid(raise_exception=True)
268
+
269
+ user = UserService.create_user(**serializer.validated_data)
270
+ return Response(UserSerializer(user).data, status=status.HTTP_201_CREATED)
271
+
272
+
273
+ @api_view(["DELETE"])
274
+ @permission_classes([IsAuthenticated])
275
+ def deactivate_user(request: Request, user_id: str) -> Response:
276
+ UserService.deactivate_user(user_id=user_id)
277
+ return Response(status=status.HTTP_204_NO_CONTENT)
278
+ ```
279
+
280
+ ## Testing with pytest-django
281
+
282
+ ### Test Factories
283
+
284
+ ```python
285
+ # apps/users/tests/factories.py
286
+ import factory
287
+ from factory.django import DjangoModelFactory
288
+ from apps.users.models import User
289
+
290
+
291
+ class UserFactory(DjangoModelFactory):
292
+ class Meta:
293
+ model = User
294
+
295
+ email = factory.Sequence(lambda n: f"user{n}@example.com")
296
+ username = factory.Sequence(lambda n: f"user{n}")
297
+ password = factory.PostGenerationMethodCall("set_password", "testpass123")
298
+ is_active = True
299
+ ```
300
+
301
+ ### Service Tests
302
+
303
+ ```python
304
+ # apps/users/tests/test_services.py
305
+ import pytest
306
+ from apps.users.services import UserService
307
+
308
+
309
+ @pytest.mark.django_db
310
+ class TestUserService:
311
+
312
+ def test_create_user_succeeds_with_valid_data(self):
313
+ user = UserService.create_user(
314
+ email="new@example.com",
315
+ password="secure123",
316
+ username="newuser",
317
+ )
318
+
319
+ assert user.pk is not None
320
+ assert user.email == "new@example.com"
321
+ assert user.check_password("secure123")
322
+
323
+ def test_create_user_raises_when_email_exists(self, user_factory):
324
+ existing = user_factory(email="taken@example.com")
325
+
326
+ with pytest.raises(ValueError, match="already registered"):
327
+ UserService.create_user(
328
+ email=existing.email,
329
+ password="any",
330
+ username="other",
331
+ )
332
+ ```
333
+
334
+ ### View Tests
335
+
336
+ ```python
337
+ # apps/users/tests/test_views.py
338
+ import pytest
339
+ from django.urls import reverse
340
+
341
+
342
+ @pytest.mark.django_db
343
+ class TestCreateUser:
344
+
345
+ def test_returns_201_with_valid_payload(self, client):
346
+ response = client.post(
347
+ reverse("users:create"),
348
+ data={"email": "new@example.com", "password": "secure123", "username": "new"},
349
+ content_type="application/json",
350
+ )
351
+
352
+ assert response.status_code == 201
353
+ assert response.data["email"] == "new@example.com"
354
+
355
+ def test_returns_400_with_invalid_email(self, client):
356
+ response = client.post(
357
+ reverse("users:create"),
358
+ data={"email": "not-an-email", "password": "x", "username": "y"},
359
+ content_type="application/json",
360
+ )
361
+
362
+ assert response.status_code == 400
363
+
364
+ def test_returns_400_when_email_already_exists(self, client, user_factory):
365
+ user_factory(email="taken@example.com")
366
+
367
+ response = client.post(
368
+ reverse("users:create"),
369
+ data={"email": "taken@example.com", "password": "pass", "username": "z"},
370
+ content_type="application/json",
371
+ )
372
+
373
+ assert response.status_code == 400
374
+ ```
375
+
376
+ ### conftest.py
377
+
378
+ ```python
379
+ # conftest.py
380
+ import pytest
381
+ from pytest_factoryboy import register
382
+ from apps.users.tests.factories import UserFactory
383
+
384
+ register(UserFactory) # makes user_factory fixture available everywhere
385
+ ```
386
+
387
+ ## Linting
388
+
389
+ ```bash
390
+ # Check
391
+ uv run ruff check .
392
+
393
+ # Fix auto-fixable issues
394
+ uv run ruff check --fix .
395
+
396
+ # Format
397
+ uv run ruff format .
398
+ ```
399
+
400
+ Run ruff in CI on every pull request. Do not merge code that fails lint.