devhive 0.1.24__tar.gz → 0.1.26__tar.gz

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 (53) hide show
  1. {devhive-0.1.24/devhive.egg-info → devhive-0.1.26}/PKG-INFO +4 -1
  2. {devhive-0.1.24 → devhive-0.1.26}/README.md +3 -0
  3. {devhive-0.1.24 → devhive-0.1.26/devhive.egg-info}/PKG-INFO +4 -1
  4. {devhive-0.1.24 → devhive-0.1.26}/devhive.egg-info/SOURCES.txt +2 -0
  5. {devhive-0.1.24 → devhive-0.1.26}/devhive_cli/main.py +34 -0
  6. devhive-0.1.26/devhive_cli/templates_backend.py +383 -0
  7. {devhive-0.1.24 → devhive-0.1.26}/setup.py +1 -1
  8. devhive-0.1.26/templates/AGENTS.backend.md +54 -0
  9. {devhive-0.1.24 → devhive-0.1.26}/LICENSE +0 -0
  10. {devhive-0.1.24 → devhive-0.1.26}/MANIFEST.in +0 -0
  11. {devhive-0.1.24 → devhive-0.1.26}/community_skills/architecture-patterns/SKILL.md +0 -0
  12. {devhive-0.1.24 → devhive-0.1.26}/community_skills/architecture-patterns/resources/implementation-playbook.md +0 -0
  13. {devhive-0.1.24 → devhive-0.1.26}/community_skills/backend-arthitect/SKILL.md +0 -0
  14. {devhive-0.1.24 → devhive-0.1.26}/community_skills/backend-security-coder/SKILL.md +0 -0
  15. {devhive-0.1.24 → devhive-0.1.26}/community_skills/docker-expert/SKILL.md +0 -0
  16. {devhive-0.1.24 → devhive-0.1.26}/community_skills/frontend-design/SKILL.md +0 -0
  17. {devhive-0.1.24 → devhive-0.1.26}/community_skills/frontend-developer/SKILL.md +0 -0
  18. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/SKILL.md +0 -0
  19. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/theme-showcase.pdf +0 -0
  20. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/arctic-frost.md +0 -0
  21. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/botanical-garden.md +0 -0
  22. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/desert-rose.md +0 -0
  23. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/forest-canopy.md +0 -0
  24. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/golden-hour.md +0 -0
  25. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/midnight-galaxy.md +0 -0
  26. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/modern-minimalist.md +0 -0
  27. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/ocean-depths.md +0 -0
  28. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/sunset-boulevard.md +0 -0
  29. {devhive-0.1.24 → devhive-0.1.26}/community_skills/theme-factory/themes/tech-innovation.md +0 -0
  30. {devhive-0.1.24 → devhive-0.1.26}/devhive.egg-info/dependency_links.txt +0 -0
  31. {devhive-0.1.24 → devhive-0.1.26}/devhive.egg-info/entry_points.txt +0 -0
  32. {devhive-0.1.24 → devhive-0.1.26}/devhive.egg-info/requires.txt +0 -0
  33. {devhive-0.1.24 → devhive-0.1.26}/devhive.egg-info/top_level.txt +0 -0
  34. {devhive-0.1.24 → devhive-0.1.26}/devhive_cli/__init__.py +0 -0
  35. {devhive-0.1.24 → devhive-0.1.26}/setup.cfg +0 -0
  36. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_architect/SKILL.md +0 -0
  37. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_auditor/SKILL.md +0 -0
  38. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_backender/SKILL.md +0 -0
  39. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_dba/SKILL.md +0 -0
  40. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_designer/SKILL.md +0 -0
  41. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_devops/SKILL.md +0 -0
  42. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_explorer/SKILL.md +0 -0
  43. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_frontender/SKILL.md +0 -0
  44. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_orchestrator/SKILL.md +0 -0
  45. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_perf/SKILL.md +0 -0
  46. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_proposal/SKILL.md +0 -0
  47. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_qa/SKILL.md +0 -0
  48. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_releaser/SKILL.md +0 -0
  49. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_sast/SKILL.md +0 -0
  50. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_taskplanner/SKILL.md +0 -0
  51. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_techwriter/SKILL.md +0 -0
  52. {devhive-0.1.24 → devhive-0.1.26}/skills/devhive_workflow.md +0 -0
  53. {devhive-0.1.24 → devhive-0.1.26}/templates/AGENTS.frontend.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devhive
3
- Version: 0.1.24
3
+ Version: 0.1.26
4
4
  Summary: CLI to manage DevHive skills and autonomous AI agents for OpenCode.
5
5
  Home-page: https://github.com/ramBlanco/devhive
6
6
  Author: ramBlanco
@@ -68,6 +68,9 @@ devhive update-skill
68
68
 
69
69
  # Initialize a modern Next.js/React frontend AI guidelines file in your current project
70
70
  devhive init-frontend
71
+
72
+ # Initialize a Hexagonal Architecture backend AI guidelines file (Interactive Prompt)
73
+ devhive init-backend
71
74
  ```
72
75
 
73
76
  ## Usage (The `@devhive` Agent)
@@ -45,6 +45,9 @@ devhive update-skill
45
45
 
46
46
  # Initialize a modern Next.js/React frontend AI guidelines file in your current project
47
47
  devhive init-frontend
48
+
49
+ # Initialize a Hexagonal Architecture backend AI guidelines file (Interactive Prompt)
50
+ devhive init-backend
48
51
  ```
49
52
 
50
53
  ## Usage (The `@devhive` Agent)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devhive
3
- Version: 0.1.24
3
+ Version: 0.1.26
4
4
  Summary: CLI to manage DevHive skills and autonomous AI agents for OpenCode.
5
5
  Home-page: https://github.com/ramBlanco/devhive
6
6
  Author: ramBlanco
@@ -68,6 +68,9 @@ devhive update-skill
68
68
 
69
69
  # Initialize a modern Next.js/React frontend AI guidelines file in your current project
70
70
  devhive init-frontend
71
+
72
+ # Initialize a Hexagonal Architecture backend AI guidelines file (Interactive Prompt)
73
+ devhive init-backend
71
74
  ```
72
75
 
73
76
  ## Usage (The `@devhive` Agent)
@@ -29,6 +29,7 @@ devhive.egg-info/requires.txt
29
29
  devhive.egg-info/top_level.txt
30
30
  devhive_cli/__init__.py
31
31
  devhive_cli/main.py
32
+ devhive_cli/templates_backend.py
32
33
  skills/devhive_workflow.md
33
34
  skills/devhive_architect/SKILL.md
34
35
  skills/devhive_auditor/SKILL.md
@@ -46,4 +47,5 @@ skills/devhive_releaser/SKILL.md
46
47
  skills/devhive_sast/SKILL.md
47
48
  skills/devhive_taskplanner/SKILL.md
48
49
  skills/devhive_techwriter/SKILL.md
50
+ templates/AGENTS.backend.md
49
51
  templates/AGENTS.frontend.md
@@ -3,6 +3,7 @@ import shutil
3
3
  import subprocess
4
4
  from pathlib import Path
5
5
  import click
6
+ from devhive_cli.templates_backend import generate_backend_agents_md
6
7
 
7
8
  # Paths configuration
8
9
  CLI_DIR = Path(__file__).resolve().parent
@@ -93,5 +94,38 @@ def init_frontend():
93
94
  shutil.copy2(template_path, dest_path)
94
95
  click.secho("✅ Successfully created AGENTS.md with modern Next.js/React frontend guidelines!", fg="green", bold=True)
95
96
 
97
+ @cli.command()
98
+ def init_backend():
99
+ """Initialize a modern backend AGENTS.md template with Hexagonal Architecture."""
100
+ dest_path = Path.cwd() / "AGENTS.md"
101
+
102
+ if dest_path.exists():
103
+ click.secho("AGENTS.md already exists in this directory. Aborting to prevent overwrite.", fg="yellow")
104
+ return
105
+
106
+ language = click.prompt("Which backend language?", type=click.Choice(['python', 'node']))
107
+
108
+ use_di = False
109
+ if language == 'python':
110
+ framework = click.prompt("Which framework?", type=click.Choice(['fastapi', 'django', 'none']))
111
+ else:
112
+ framework = click.prompt("Which framework?", type=click.Choice(['express', 'nestjs', 'none']))
113
+ if framework != 'nestjs':
114
+ use_di = click.confirm("Do you want to use InversifyJS for Dependency Injection?")
115
+
116
+ iac = click.prompt("Which IaC tool are you using?", type=click.Choice(['cdk', 'terraform', 'serverless']))
117
+
118
+ template_path = TEMPLATES_DIR / "AGENTS.backend.md"
119
+ if not template_path.exists():
120
+ click.secho("Error: Backend template not found in the devhive package.", fg="red")
121
+ return
122
+
123
+ md_content = generate_backend_agents_md(template_path, language, framework, iac, use_di)
124
+
125
+ with open(dest_path, "w", encoding="utf-8") as f:
126
+ f.write(md_content)
127
+
128
+ click.secho("✅ Successfully created AGENTS.md with Hexagonal Architecture guidelines!", fg="green", bold=True)
129
+
96
130
  if __name__ == "__main__":
97
131
  cli()
@@ -0,0 +1,383 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ def generate_backend_agents_md(template_path: Path, language: str, framework: str, iac: str, use_di: bool) -> str:
5
+ stack_list = []
6
+ if language == 'python':
7
+ stack_list.append("- **Language**: Python 3.10+ (Strict Type Hinting)")
8
+ if framework == 'fastapi':
9
+ stack_list.append("- **Framework**: FastAPI")
10
+ elif framework == 'django':
11
+ stack_list.append("- **Framework**: Django")
12
+ else:
13
+ stack_list.append("- **Framework**: None (Pure Python / Lambdas)")
14
+ else:
15
+ stack_list.append("- **Language**: Node.js + TypeScript (Strict Mode)")
16
+ if framework == 'express':
17
+ stack_list.append("- **Framework**: Express")
18
+ elif framework == 'nestjs':
19
+ stack_list.append("- **Framework**: NestJS (Built-in DI)")
20
+ use_di = False # NestJS has its own DI
21
+ else:
22
+ stack_list.append("- **Framework**: None (Pure Node.js / Lambdas)")
23
+
24
+ if use_di:
25
+ stack_list.append("- **Dependency Injection**: InversifyJS")
26
+
27
+ if iac == 'cdk':
28
+ stack_list.append("- **Infrastructure as Code**: AWS CDK")
29
+ elif iac == 'terraform':
30
+ stack_list.append("- **Infrastructure as Code**: Terraform")
31
+ else:
32
+ stack_list.append("- **Infrastructure as Code**: Serverless Framework")
33
+
34
+ stack_section = "\n".join(stack_list)
35
+ iac_tool_upper = iac.upper()
36
+
37
+ di_rules = ""
38
+ if language == 'node' and use_di:
39
+ di_rules = """
40
+ 4. **InversifyJS Usage**:
41
+ - Decorate concrete adapters in `infrastructure/` with `@injectable()`.
42
+ - Bind interfaces to symbols in an `inversify.config.ts` container file.
43
+ - Use the container in the `presentation/` layer to resolve use cases.
44
+ """
45
+
46
+ code_examples = ""
47
+ if language == 'python':
48
+ if framework == 'fastapi':
49
+ code_examples = """### Example: FastAPI + Hexagonal Architecture
50
+
51
+ **1. Port (Application Layer)**
52
+ *File: `src/application/ports/user_repository.py`*
53
+ ```python
54
+ from typing import Protocol
55
+ from src.domain.entities.user import User
56
+
57
+ class UserRepository(Protocol):
58
+ def get_by_id(self, user_id: str) -> User | None:
59
+ ...
60
+ ```
61
+
62
+ **2. Adapter (Infrastructure Layer)**
63
+ *File: `src/infrastructure/database/postgres_user_repository.py`*
64
+ ```python
65
+ from src.application.ports.user_repository import UserRepository
66
+ from src.domain.entities.user import User
67
+
68
+ class PostgresUserRepository:
69
+ def __init__(self, db_session):
70
+ self.db = db_session
71
+
72
+ def get_by_id(self, user_id: str) -> User | None:
73
+ # DB logic here returning Domain Entity
74
+ return User(id=user_id, name="Alice")
75
+ ```
76
+
77
+ **3. Use Case (Application Layer)**
78
+ *File: `src/application/use_cases/get_user.py`*
79
+ ```python
80
+ from src.application.ports.user_repository import UserRepository
81
+ from src.domain.entities.user import User
82
+ from src.domain.exceptions import UserNotFoundError
83
+
84
+ class GetUserUseCase:
85
+ def __init__(self, user_repo: UserRepository):
86
+ self.user_repo = user_repo
87
+
88
+ def execute(self, user_id: str) -> User:
89
+ user = self.user_repo.get_by_id(user_id)
90
+ if not user:
91
+ raise UserNotFoundError(f"User {user_id} not found")
92
+ return user
93
+ ```
94
+
95
+ **4. Controller (Presentation Layer)**
96
+ *File: `src/presentation/controllers/user_controller.py`*
97
+ ```python
98
+ from fastapi import APIRouter, Depends, HTTPException
99
+ from src.application.use_cases.get_user import GetUserUseCase
100
+ from src.infrastructure.database.postgres_user_repository import PostgresUserRepository
101
+ from src.domain.exceptions import UserNotFoundError
102
+
103
+ router = APIRouter()
104
+
105
+ # Poor man's DI for FastAPI
106
+ def get_user_use_case() -> GetUserUseCase:
107
+ repo = PostgresUserRepository(db_session=None)
108
+ return GetUserUseCase(user_repo=repo)
109
+
110
+ @router.get("/users/{user_id}")
111
+ def get_user(user_id: str, use_case: GetUserUseCase = Depends(get_user_use_case)):
112
+ try:
113
+ return use_case.execute(user_id)
114
+ except UserNotFoundError as e:
115
+ raise HTTPException(status_code=404, detail=str(e))
116
+ ```
117
+ """
118
+ elif framework == 'django':
119
+ code_examples = """### Example: Django + Hexagonal Architecture
120
+
121
+ **Note on Django**: Do NOT put business logic in Django Views or Models. Use Django ONLY as the `infrastructure/` and `presentation/` layers.
122
+
123
+ **1. Port (Application Layer)**
124
+ *File: `src/application/ports/user_repository.py`*
125
+ ```python
126
+ import abc
127
+ from src.domain.entities.user import User
128
+
129
+ class UserRepository(abc.ABC):
130
+ @abc.abstractmethod
131
+ def get_by_id(self, user_id: str) -> User | None:
132
+ pass
133
+ ```
134
+
135
+ **2. Adapter (Infrastructure Layer)**
136
+ *File: `src/infrastructure/database/django_user_repository.py`*
137
+ ```python
138
+ from src.application.ports.user_repository import UserRepository
139
+ from src.domain.entities.user import User
140
+ from myapp.models import DjangoUserModel # Django ORM Model
141
+
142
+ class DjangoUserRepository(UserRepository):
143
+ def get_by_id(self, user_id: str) -> User | None:
144
+ try:
145
+ orm_user = DjangoUserModel.objects.get(id=user_id)
146
+ return User(id=str(orm_user.id), name=orm_user.name) # Map ORM to Domain
147
+ except DjangoUserModel.DoesNotExist:
148
+ return None
149
+ ```
150
+
151
+ **3. Controller (Presentation Layer)**
152
+ *File: `src/presentation/views/user_views.py`*
153
+ ```python
154
+ from django.http import JsonResponse
155
+ from src.application.use_cases.get_user import GetUserUseCase
156
+ from src.infrastructure.database.django_user_repository import DjangoUserRepository
157
+ from src.domain.exceptions import UserNotFoundError
158
+
159
+ def get_user_view(request, user_id: str):
160
+ repo = DjangoUserRepository()
161
+ use_case = GetUserUseCase(user_repo=repo)
162
+
163
+ try:
164
+ user = use_case.execute(user_id)
165
+ return JsonResponse({"id": user.id, "name": user.name})
166
+ except UserNotFoundError as e:
167
+ return JsonResponse({"error": str(e)}, status=404)
168
+ ```
169
+ """
170
+ else:
171
+ code_examples = """### Example: Pure Python + Hexagonal Architecture
172
+
173
+ **1. Port (Application Layer)**
174
+ *File: `src/application/ports/user_repository.py`*
175
+ ```python
176
+ from typing import Protocol
177
+ from src.domain.entities.user import User
178
+
179
+ class UserRepository(Protocol):
180
+ def get_by_id(self, user_id: str) -> User | None:
181
+ ...
182
+ ```
183
+
184
+ **2. Use Case (Application Layer)**
185
+ *File: `src/application/use_cases/get_user.py`*
186
+ ```python
187
+ from src.application.ports.user_repository import UserRepository
188
+ from src.domain.entities.user import User
189
+
190
+ class GetUserUseCase:
191
+ def __init__(self, user_repo: UserRepository):
192
+ self.user_repo = user_repo
193
+
194
+ def execute(self, user_id: str) -> User:
195
+ return self.user_repo.get_by_id(user_id)
196
+ ```
197
+
198
+ **3. Handler (Presentation Layer - Lambda)**
199
+ *File: `src/presentation/handlers/user_handler.py`*
200
+ ```python
201
+ from src.application.use_cases.get_user import GetUserUseCase
202
+ from src.infrastructure.database.dynamo_user_repository import DynamoUserRepository
203
+
204
+ # Initialize dependencies at the module level for Lambda cold starts
205
+ repo = DynamoUserRepository()
206
+ use_case = GetUserUseCase(user_repo=repo)
207
+
208
+ def lambda_handler(event, context):
209
+ user_id = event.get('pathParameters', {}).get('userId')
210
+ user = use_case.execute(user_id)
211
+ return {"statusCode": 200, "body": user.to_json()}
212
+ ```
213
+ """
214
+ else: # Node.js
215
+ if use_di:
216
+ code_examples = """### Example: Node.js + TypeScript + InversifyJS
217
+
218
+ **1. Port (Application Layer)**
219
+ *File: `src/application/ports/IUserRepository.ts`*
220
+ ```typescript
221
+ import { User } from "../../domain/entities/User";
222
+
223
+ export const TYPES = {
224
+ IUserRepository: Symbol.for("IUserRepository"),
225
+ GetUserUseCase: Symbol.for("GetUserUseCase"),
226
+ };
227
+
228
+ export interface IUserRepository {
229
+ getById(userId: string): Promise<User | null>;
230
+ }
231
+ ```
232
+
233
+ **2. Adapter (Infrastructure Layer)**
234
+ *File: `src/infrastructure/database/PostgresUserRepository.ts`*
235
+ ```typescript
236
+ import { injectable } from "inversify";
237
+ import "reflect-metadata";
238
+ import { IUserRepository } from "../../application/ports/IUserRepository";
239
+ import { User } from "../../domain/entities/User";
240
+
241
+ @injectable()
242
+ export class PostgresUserRepository implements IUserRepository {
243
+ async getById(userId: string): Promise<User | null> {
244
+ // DB Logic returning Domain Entity
245
+ return new User(userId, "Alice");
246
+ }
247
+ }
248
+ ```
249
+
250
+ **3. Use Case (Application Layer)**
251
+ *File: `src/application/useCases/GetUserUseCase.ts`*
252
+ ```typescript
253
+ import { inject, injectable } from "inversify";
254
+ import "reflect-metadata";
255
+ import { IUserRepository, TYPES } from "../ports/IUserRepository";
256
+ import { User } from "../../domain/entities/User";
257
+
258
+ @injectable()
259
+ export class GetUserUseCase {
260
+ constructor(
261
+ @inject(TYPES.IUserRepository) private userRepository: IUserRepository
262
+ ) {}
263
+
264
+ async execute(userId: string): Promise<User> {
265
+ const user = await this.userRepository.getById(userId);
266
+ if (!user) throw new Error("User not found");
267
+ return user;
268
+ }
269
+ }
270
+ ```
271
+
272
+ **4. DI Container Setup (Infrastructure Layer)**
273
+ *File: `src/infrastructure/di/container.ts`*
274
+ ```typescript
275
+ import { Container } from "inversify";
276
+ import { TYPES, IUserRepository } from "../../application/ports/IUserRepository";
277
+ import { PostgresUserRepository } from "../database/PostgresUserRepository";
278
+ import { GetUserUseCase } from "../../application/useCases/GetUserUseCase";
279
+
280
+ const container = new Container();
281
+
282
+ container.bind<IUserRepository>(TYPES.IUserRepository).to(PostgresUserRepository);
283
+ container.bind<GetUserUseCase>(TYPES.GetUserUseCase).to(GetUserUseCase);
284
+
285
+ export { container };
286
+ ```
287
+
288
+ **5. Controller (Presentation Layer)**
289
+ *File: `src/presentation/controllers/UserController.ts`*
290
+ ```typescript
291
+ import { Request, Response } from "express";
292
+ import { container } from "../../infrastructure/di/container";
293
+ import { TYPES } from "../../application/ports/IUserRepository";
294
+ import { GetUserUseCase } from "../../application/useCases/GetUserUseCase";
295
+
296
+ export class UserController {
297
+ async getUser(req: Request, res: Response) {
298
+ const useCase = container.get<GetUserUseCase>(TYPES.GetUserUseCase);
299
+ try {
300
+ const user = await useCase.execute(req.params.id);
301
+ res.json(user);
302
+ } catch (error) {
303
+ res.status(404).json({ error: error.message });
304
+ }
305
+ }
306
+ }
307
+ ```
308
+ """
309
+ else:
310
+ code_examples = """### Example: Node.js + TypeScript (Manual DI)
311
+
312
+ **1. Port (Application Layer)**
313
+ *File: `src/application/ports/IUserRepository.ts`*
314
+ ```typescript
315
+ import { User } from "../../domain/entities/User";
316
+
317
+ export interface IUserRepository {
318
+ getById(userId: string): Promise<User | null>;
319
+ }
320
+ ```
321
+
322
+ **2. Adapter (Infrastructure Layer)**
323
+ *File: `src/infrastructure/database/PostgresUserRepository.ts`*
324
+ ```typescript
325
+ import { IUserRepository } from "../../application/ports/IUserRepository";
326
+ import { User } from "../../domain/entities/User";
327
+
328
+ export class PostgresUserRepository implements IUserRepository {
329
+ async getById(userId: string): Promise<User | null> {
330
+ // DB Logic returning Domain Entity
331
+ return new User(userId, "Alice");
332
+ }
333
+ }
334
+ ```
335
+
336
+ **3. Use Case (Application Layer)**
337
+ *File: `src/application/useCases/GetUserUseCase.ts`*
338
+ ```typescript
339
+ import { IUserRepository } from "../ports/IUserRepository";
340
+ import { User } from "../../domain/entities/User";
341
+
342
+ export class GetUserUseCase {
343
+ constructor(private userRepository: IUserRepository) {}
344
+
345
+ async execute(userId: string): Promise<User> {
346
+ const user = await this.userRepository.getById(userId);
347
+ if (!user) throw new Error("User not found");
348
+ return user;
349
+ }
350
+ }
351
+ ```
352
+
353
+ **4. Controller (Presentation Layer)**
354
+ *File: `src/presentation/controllers/UserController.ts`*
355
+ ```typescript
356
+ import { Request, Response } from "express";
357
+ import { GetUserUseCase } from "../../application/useCases/GetUserUseCase";
358
+ import { PostgresUserRepository } from "../../infrastructure/database/PostgresUserRepository";
359
+
360
+ export class UserController {
361
+ async getUser(req: Request, res: Response) {
362
+ const repo = new PostgresUserRepository();
363
+ const useCase = new GetUserUseCase(repo);
364
+ try {
365
+ const user = await useCase.execute(req.params.id);
366
+ res.json(user);
367
+ } catch (error) {
368
+ res.status(404).json({ error: error.message });
369
+ }
370
+ }
371
+ }
372
+ ```
373
+ """
374
+
375
+ with open(template_path, 'r', encoding='utf-8') as f:
376
+ md = f.read()
377
+
378
+ md = md.replace("{{TECH_STACK}}", stack_section)
379
+ md = md.replace("{{IAC_TOOL}}", iac_tool_upper)
380
+ md = md.replace("{{DI_RULES}}", di_rules)
381
+ md = md.replace("{{CODE_EXAMPLES}}", code_examples)
382
+
383
+ return md
@@ -8,7 +8,7 @@ with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
8
8
 
9
9
  setup(
10
10
  name="devhive",
11
- version="0.1.24",
11
+ version="0.1.26",
12
12
  packages=find_packages(),
13
13
  include_package_data=True,
14
14
  install_requires=[
@@ -0,0 +1,54 @@
1
+ # Backend Architecture & AI Agent Guidelines
2
+
3
+ This `AGENTS.md` (or `GUIDELINES.md`) file serves as the strict instruction manual for OpenCode and DevHive agents. It defines the technical stack, architectural patterns, and coding conventions for this backend project.
4
+
5
+ ## 🛠️ 1. Tech Stack
6
+ {{TECH_STACK}}
7
+
8
+ ## 🧠 2. OpenCode Skills to Load
9
+ Agents **MUST** load the following specialized skills before executing tasks:
10
+ - `architecture-patterns`: For maintaining clean separation of concerns and Hexagonal Architecture.
11
+ - `backend-architect`: For scalable API design and domain modeling.
12
+ - `backend-security-coder`: For secure coding practices, input validation, and auth.
13
+ - `devhive-devops`: For {{IAC_TOOL}} infrastructure setup.
14
+
15
+ ## 📂 3. Project Structure (Hexagonal Architecture)
16
+ For maximum scalability, testability, and maintainability, the project MUST strictly follow Hexagonal Architecture (Ports & Adapters).
17
+
18
+ ```text
19
+ src/
20
+ ├── domain/ # ENTERPRISE BUSINESS RULES (No external dependencies)
21
+ │ ├── entities/ # Pure domain models
22
+ │ └── exceptions/ # Domain-specific errors
23
+ ├── application/ # APPLICATION BUSINESS RULES (Use Cases & Ports)
24
+ │ ├── use_cases/ # Orchestrates domain logic
25
+ │ └── ports/ # Interfaces for outbound communication (Repositories, External APIs)
26
+ ├── infrastructure/ # ADAPTERS (Database, External Services, Third-party libs)
27
+ │ ├── database/ # Concrete implementation of repository ports
28
+ │ └── di/ # Dependency Injection container/setup
29
+ └── presentation/ # ENTRY POINTS (Controllers, REST APIs, GraphQL, Lambdas)
30
+ └── controllers/ # Parses HTTP requests and calls use cases
31
+
32
+ infrastructure/ # IaC DEFINITIONS (Outside src/)
33
+ └── # {{IAC_TOOL}} configurations
34
+ ```
35
+
36
+ ## 📐 4. Architectural Rules & Clean Code (CRITICAL)
37
+
38
+ 1. **The Dependency Rule**: Source code dependencies MUST only point inward, toward the `domain/`.
39
+ - `domain/` knows nothing about anything else.
40
+ - `application/` depends only on `domain/`.
41
+ - `infrastructure/` and `presentation/` depend on `application/` and `domain/`.
42
+ - **Never import an infrastructure detail (like a DB model) into a use case.**
43
+
44
+ 2. **Ports and Adapters**:
45
+ - Outbound communication (like DB queries) MUST be defined as an interface (Port) in the `application/` layer.
46
+ - The actual database logic MUST be implemented as an Adapter in the `infrastructure/` layer.
47
+
48
+ 3. **Dependency Injection**:
49
+ - Use Cases must receive their dependencies (Ports) via constructor injection.
50
+ - The Presentation layer resolves these dependencies and passes them to the Use Cases.
51
+ {{DI_RULES}}
52
+ ## 💻 5. Code Examples
53
+
54
+ {{CODE_EXAMPLES}}
File without changes
File without changes
File without changes