# U Be Development

> Coding standards, commit conventions, folder structure, naming rules, and error handling patterns for back-end implementation. Covers routes, controllers, services, repositories, models, and middleware. Loaded by orchestrator-dev when activating the Developer agent.

- **Type:** Skill
- **Install:** `agentstack add skill-zig999-siegard-code-u-be-development`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [zig999](https://agentstack.voostack.com/s/zig999)
- **Installs:** 0
- **Category:** [Communication](https://agentstack.voostack.com/c/communication)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [zig999](https://github.com/zig999)
- **Source:** https://github.com/zig999/siegard-code/tree/main/dist/.claude/skills/u-be-development

## Install

```sh
agentstack add skill-zig999-siegard-code-u-be-development
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# SKILL: Development (Backend)

## Purpose
This skill defines how the Developer Agent must structure, name, organize, and deliver code — ensuring consistency across Task Contracts and predictability for the QA Agent.

---

## Customization via CLAUDE.md

> Precedence rule defined in `orchestrator-core.md`. Not repeated here.

Before creating any file, extract from `CLAUDE.md`:

| What to look for | Used in |
|---|---|
| Project folder structure | Where to create new files |
| Naming conventions | File, class, and function names |
| Testing framework/library | How to write and run tests |
| Configured logger | Replace `console.log` |
| Custom error pattern | Error classes to extend |
| Already defined environment variables | Avoid hardcoding and duplicates |
| Configured ORM/ODM | Model and migration patterns |
| `validation_library` | DTO schema strategy (Zod, Joi, class-validator) |
| `di_strategy` | Dependency injection pattern (manual-factory, nestjs-ioc, inversify) |
| `pagination.strategy` | Offset or cursor pagination — determines `PaginatedResponse` meta shape |

If `CLAUDE.md` does not cover a given point, use the defaults from this skill and document the decision in the delivery file.

---

## Engineering principles

- Follow CLEAN Code and SOLID principles rigorously
- Apply appropriate design patterns whenever relevant (Factory, Strategy, Repository, Observer, etc.)
- Prefer composition over inheritance
- Apply Dependency Injection for all external dependencies (database, APIs, services)
- Prefer pure functions and immutability whenever possible
- Every public function/method must have a single, clear responsibility
- Prioritize simplicity: small, focused modules without unnecessary complexity
- Simplify first: avoid accidental complexity, YAGNI, and premature abstractions

---

## Progress reporting (mandatory)

Emit `task_progress` at each checkpoint before proceeding to the next phase of work. These events reset the stale detection timer and give the orchestrator visibility during long-running tasks.

```bash
# Checkpoint 1 — after reading and validating the task spec
python3 .claude/skills/orch-log/scripts/append.py \
  --agent $ORCH_WORKER_ID --event-type task_progress \
  --task-id $ORCH_TASK_ID --attempt $ORCH_ATTEMPT \
  --data '{"phase":"dev","checkpoint":"spec_validated"}'

# Checkpoint 2 — after analysis, before writing any code
python3 .claude/skills/orch-log/scripts/append.py \
  --agent $ORCH_WORKER_ID --event-type task_progress \
  --task-id $ORCH_TASK_ID --attempt $ORCH_ATTEMPT \
  --data '{"phase":"dev","checkpoint":"analysis_complete"}'

# Checkpoint 3 — after creating the branch, before first file write
python3 .claude/skills/orch-log/scripts/append.py \
  --agent $ORCH_WORKER_ID --event-type task_progress \
  --task-id $ORCH_TASK_ID --attempt $ORCH_ATTEMPT \
  --data '{"phase":"dev","checkpoint":"branch_created"}'

# Checkpoint 4 — after all source code is written, before tests
python3 .claude/skills/orch-log/scripts/append.py \
  --agent $ORCH_WORKER_ID --event-type task_progress \
  --task-id $ORCH_TASK_ID --attempt $ORCH_ATTEMPT \
  --data '{"phase":"dev","checkpoint":"implementation_done"}'

# Checkpoint 5 — after tests are written, before delivery.md
python3 .claude/skills/orch-log/scripts/append.py \
  --agent $ORCH_WORKER_ID --event-type task_progress \
  --task-id $ORCH_TASK_ID --attempt $ORCH_ATTEMPT \
  --data '{"phase":"dev","checkpoint":"tests_written"}'
```

Never skip a checkpoint. If `$ORCH_WORKER_ID`, `$ORCH_TASK_ID`, or `$ORCH_ATTEMPT` are unresolved, stop and emit `task_failed` with `reason: unresolved_context_variables, retryable: false`.

---

## Terminal event guarantee (mandatory)

Before stopping for any reason — tool failure, blocked state, unexpected error, context limit — verify that a terminal event (`task_completed` or `task_failed`) has been emitted for `$ORCH_TASK_ID / $ORCH_ATTEMPT`.

**If no terminal has been emitted, emit `task_failed` immediately before stopping:**

```bash
python3 .claude/skills/orch-log/scripts/append.py \
  --agent $ORCH_WORKER_ID --event-type task_failed \
  --task-id $ORCH_TASK_ID --attempt $ORCH_ATTEMPT \
  --data '{"phase":"dev","reason":"","retryable":true}'
```

| Situation | reason | retryable |
|-----------|--------|-----------|
| Tool call denied or failed | `tool_failure` | `true` |
| Required file not found | `missing_input:` | `false` |
| Implementation blocked by ambiguity | `blocked_ambiguity` | `false` |
| Context limit approaching | `context_limit` | `true` |
| Unresolved env variables | `unresolved_context_variables` | `false` |
| Any other unexpected stop | `unexpected_exit` | `true` |

The `on_subagent_stop` hook synthesizes `task_failed` if this rule is not followed, but explicit emission is always preferred — it carries an accurate reason and retryable flag.

---

## Mandatory flow before coding

```
1. Read the full Task Contract (narrative + all acceptance criteria)
   → emit checkpoint: spec_validated
2. Read the files listed as dependencies in the previous delivery (if any)
3. Map the interface contracts the Task Contract will touch or create
   → emit checkpoint: analysis_complete
4. Confirm you are on the Task Contract branch the Orchestrator created (feat/TC-XX, fix/TC-XX, or refactor/TC-XX) in your worktree
   → emit checkpoint: branch_created
5. Write the implementation plan as a comment at the top of the first file created
6. Only then begin implementation
   → emit checkpoint: implementation_done (after all source code is written, before tests)
7. Write tests
   → emit checkpoint: tests_written (after tests, before delivery.md)
```

If any step reveals a blocking ambiguity -> **stop, emit `task_failed` with `reason: blocked_ambiguity, retryable: false`, and record the ambiguity in the delivery file**.

---

## Branch and commits

### Branch per Task Contract

The Orchestrator-Dev creates one branch + worktree per Task Contract from `main` before activating you (SIEGARD-04). Confirm you are on it before any implementation:

```
feat/TC-XX     `CLAUDE.md` conventions take precedence (see precedence rule in orchestrator-core).

---

## TypeScript code quality

- Strict TypeScript: enable `strict: true`, `noImplicitAny`, `strictNullChecks`
- Never use `any` — prefer `unknown`, generics, or explicit types
- Avoid `as` type assertions; use type guards and narrowing
- Define explicit types on public function signatures (parameters and return)
- Use `readonly` for properties that must not be reassigned
- Prefer `const enum` or union types over conventional enums
- Use the `Result` or Either pattern for operations that can fail (avoid throw in business logic)
- Limit functions to ~30 lines; extract complex logic into named helpers
- Maximum of 3 parameters per function — use objects for more
- Avoid magic numbers and magic strings — extract named constants

---

## Architecture

- Adopt layered architecture (Layered/Clean Architecture) or Hexagonal when applicable
- Minimum layers: Controller -> Service/UseCase -> Repository/Gateway
- Keep business rules isolated from frameworks and I/O
- Use Ports & Adapters for external integrations (database, queues, third-party APIs)
- Domain entities must not depend on external libraries
- Each module/domain must be self-contained — avoid circular dependencies
- Clearly separate configuration, bootstrap, and application logic

---

## Dependency Injection

**Default strategy: manual factory function per module.**

Read `di_strategy` from `CLAUDE.md`. If absent, use `manual-factory`.

| `di_strategy` value | Pattern |
|---|---|
| `manual-factory` | Factory function in `src/factories/[resource].factory.ts` — explicit wiring |
| `nestjs-ioc` | NestJS `@Injectable()` — follow framework conventions |
| `inversify` | InversifyJS container — declare bindings in `src/config/container.ts` |

**Manual factory pattern (default):**

```typescript
// src/factories/user.factory.ts
import { DatabaseClient } from "@/config/database";
import { UserRepository } from "@/repositories/user.repository";
import { UserService }    from "@/services/user.service";
import { UserController } from "@/controllers/user.controller";

export function createUserModule(db: DatabaseClient) {
  const repository = new UserRepository(db);
  const service    = new UserService(repository);
  const controller = new UserController(service);
  return { repository, service, controller };
}
```

**Rules (all strategies):**
- Constructors receive **interfaces**, never concrete classes
- Never instantiate a dependency inside a service — receive via constructor
- Never use `new SomeService()` inline in a controller or route
- Factory functions are the only place where `new` is used to wire dependencies

---

## DTO Pattern

**Default library: Zod** — unless `CLAUDE.md` declares `validation_library`.

| `validation_library` value | Pattern |
|---|---|
| `zod` | `z.object(...)` schema + `z.infer` type (default) |
| `class-validator` | Class with decorators — follows NestJS conventions |
| `joi` | `Joi.object(...)` schema + explicit TypeScript type |

**Zod default — naming and file conventions:**

```typescript
// src/dto/create-user.dto.ts
import { z } from "zod";

export const CreateUserSchema = z.object({
  name:  z.string().min(1).max(255),
  email: z.string().email(),
});

export type CreateUserDto = z.infer;
```

| Use case | Schema name | Inferred type | File |
|---|---|---|---|
| Create | `Create{Resource}Schema` | `Create{Resource}Dto` | `create-{resource}.dto.ts` |
| Update | `Update{Resource}Schema` | `Update{Resource}Dto` | `update-{resource}.dto.ts` |
| API response | `{Resource}ResponseSchema` | `{Resource}Response` | `{resource}-response.dto.ts` |
| Query params | `List{Resource}QuerySchema` | `List{Resource}Query` | `list-{resource}-query.dto.ts` |

**Rules:**
- Schema name = `PascalCase + "Schema"`; type name = `PascalCase + "Dto"` or `"Response"`
- Validate at the route/middleware boundary — service receives an already-typed DTO, never raw `req.body`
- DTOs live in `src/dto/` (flat) or `src/modules/{domain}/dto/` (module structure) — never inline in controllers
- Do not redefine the same schema in tests — import from `src/dto/`

---

## Default folder structure

```
src/
├── routes/              , OffsetPaginationMeta, CursorPaginationMeta
│   └── index.ts
├── factories/            Adapt according to the structure defined in `CLAUDE.md`.

**Module-based alternative** (when `CLAUDE.md` declares `folder_structure: modules`):
```
src/modules/{domain}/
    controller/   dto/   service/   repository/   entity/   factory/
```
In this case `src/types/pagination.ts` and `src/types/api.ts` remain at the root `src/types/` — never duplicated per module.

---

## Mandatory tests and quality criteria

> Refer to `standards/SKILL.md` for the mandatory tests per Task Contract type table and test quality criteria. Tests are part of the delivery — the QA Agent does not write tests; it validates the coverage of the tests you delivered.

---

## Error handling

Every function that can fail must:

1. Use explicit error types — avoid `throw new Error("something went wrong")`
2. Differentiate operational errors (expected, e.g., resource not found) from programming errors (bugs)
3. Never silence errors with an empty `catch {}`
4. Propagate context: `throw new AppError("createUser failed", { cause: err })`

```typescript
// Bad
try {
  const user = await db.user.findUnique({ where: { id } });
  return user;
} catch (e) {
  throw new Error("error");
}

// Good
async function getUserById(id: string): Promise {
  const user = await db.user.findUnique({ where: { id } });
  if (!user) throw new NotFoundError(`User ${id} not found`);
  return user;
}
```

### Error layers

| Layer | Responsibility |
|---|---|
| Controller | Catches service errors, maps to HTTP status code |
| Service | Throws business errors (NotFound, Conflict, ValidationError) |
| Repository | Throws data errors (ConnectionError, QueryError) |
| Middleware (error handler) | Catches all unhandled errors, formats standard response |

### Mandatory fields in error classes

Every custom error class must inherit from `Error` and include:
- `name` — error class name (e.g., `NotFoundError`, `ConflictError`)
- `message` — human-readable error description
- `statusCode` — corresponding HTTP code (e.g., 404, 409, 422)
- `context` — additional diagnostic data (input, entity ID, etc.)

### Error logging

- Always log errors with sufficient context: correlation ID, relevant input, stack trace
- Never expose stack traces or internal details to the client in production

### Error response format

Error responses must follow a standardized format:

```json
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "User with ID 123 not found",
    "details": {}
  }
}
```

---

## API design

- RESTful by default; document with OpenAPI/Swagger
- Versioning via URL prefix: `/api/v1/`
- Use HTTP status codes correctly (201 for creation, 204 for delete without body, 422 for validation)
- Validate input at the boundary (controller/middleware) using DTOs from `src/dto/` — never raw `req.body` in services
- Paginated responses use `PaginatedResponse` from `src/types/pagination.ts` — never ad-hoc `{ data, meta }` shapes
- Idempotency for sensitive operations (POST with idempotency key)

---

## Pagination

Read `pagination.strategy` from `CLAUDE.md`. If absent, use `offset`.

**Shared types — always in `src/types/pagination.ts`, never duplicated per module:**

```typescript
export interface OffsetPaginationMeta {
  page:  number;
  limit: number;
  total: number;
  pages: number;          // Math.ceil(total / limit)
}

export interface CursorPaginationMeta {
  next_cursor: string | null;
  has_more:    boolean;
  limit:       number;
}

export interface PaginatedResponse {
  data: T[];
  meta: OffsetPaginationMeta | CursorPaginationMeta;
}
```

| Strategy | When to use | Query params |
|---|---|---|
| `offset` | Admin lists, reports, exports — default | `?page=1&limit=20` |
| `cursor` | Feeds, timelines, real-time streams | `?cursor=abc&limit=20` |

**Rules:**
- Never return `null` for an empty list — always `PaginatedResponse` with `data: []`
- `default_limit` and `max_limit` are read from `CLAUDE.md` — never hardcode these values
- If `limit` exceeds `max_limit`, reject with 400 and `error.code: PAGINATION_LIMIT_EXCEEDED`
- `pages` field (offset only) must always be computed — never omitted

---

## Edge cases

> Refer to the **universal checklist** and **handling patterns** in `standards/SKILL.md`. For every implemented function, handle applicable scenarios and document them in the delivery file.

---

## Explicit prohibitions

- `console.log` in production code (use the project's configured logger)
- Hardcoded credentials, tokens, or environment URLs
- `any` in TypeScript — prefer `unknown`, generics, or explicit types
- `as` type assertions without a corresponding type guard or narrowing
- Unused imports
- Commented-out code (delete it, don't comment it)
- `TODO` without a Task Contract or issue reference (`// TODO(TC-12): add cache`)
- Changing code outside the Task Contract scope without creating a separate technical Task Contract
- Raw SQL queries without parameterization (SQL injection risk)
- Secrets in logs or error messages returned to the client
- Destructive migrations without rollback (always provide `up` and `down`)

---

## Delivery file template

> When generating `tc-XX-delivery.md`, read the full template at `.claude/skills/u-be-templates/delivery.md`.

---

## Infrastructure dependency verification

Before starting implementation, the Developer must map **all infrastructure services and resources** the Task Contract requires.

### How to verify

1. Extract from the Task Contract and API Spec all infrastructure dependencies (database, queues, cache, third-party services, storage, etc.)
2. For each dependency, check whether the configuratio

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [zig999](https://github.com/zig999)
- **Source:** [zig999/siegard-code](https://github.com/zig999/siegard-code)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-zig999-siegard-code-u-be-development
- Seller: https://agentstack.voostack.com/s/zig999
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
