- name
- open-fusion-code-quality
- description
- Keep Open Fusion code maintainable with SOLID, DRY, clean architecture, and pragmatic TypeScript/NestJS design. Use when Codex designs modules, writes production code, refactors, reviews code quality, extracts abstractions, names services/adapters, or reduces duplication in the Open Fusion LLM gateway.
# Open Fusion Code Quality
## Required Context
Before judging design, read the relevant spec and ADR. For core architecture, read:
- `docs/PRD.md`
- `docs/adrs/0001-use-nestjs-backend.md`
- `docs/adrs/0003-use-vercel-ai-sdk.md`
- `docs/adrs/0007-provider-adapter-layer.md`
Use this skill with `open-fusion-tdd-cycle` for implementation changes.
## Design Principles
Apply SOLID pragmatically:
- Single Responsibility: controllers handle HTTP, config services handle config, adapters handle provider details, orchestration services handle orchestration policy.
- Open/Closed: new providers should be added by registering adapters, not editing controllers.
- Liskov Substitution: adapters must satisfy the same contract for success, stream, timeout, and error behavior.
- Interface Segregation: keep small interfaces for generation, streaming, config access, and secret resolution.
- Dependency Inversion: depend on internal abstractions, not concrete provider SDKs outside adapter modules.
Apply DRY after intent is clear:
- remove duplicated policy logic immediately;
- tolerate small duplicated tests until patterns stabilize;
- extract helpers only when they improve names and diagnostics;
- avoid generic abstractions for one provider or one endpoint.
## Open Fusion Boundaries
Keep these boundaries explicit:
- HTTP API: request validation, headers, status codes, SSE framing.
- Application orchestration: route resolution, delegate limits, final response lifecycle.
- Configuration: schema validation, env secret resolution, immutable runtime config.
- Provider adapters: Vercel AI SDK/provider specifics and error mapping.
- Observability/security: request ids, logging, redaction, auth, timeouts.
Crossing these boundaries should happen through typed interfaces.
## TypeScript Standards
- Prefer explicit domain types over loose `any`.
- Do not leave untyped locals that widen to `any` for provider, orchestration, or config results.
- Model config and API DTOs separately.
- Validate external input at boundaries before using typed runtime objects.
- Treat provider outputs as external input even when they came through an SDK type.
- Use discriminated unions for provider result/error variants when useful.
- Keep async cancellation/timeout behavior visible in function signatures or options.
- Extract shared domain types when the same request/client/config shape appears across services and Express request augmentation.
## NestJS Standards
- Keep controllers thin.
- Put business rules in injectable services.
- Use guards for auth, filters for error envelopes, interceptors/middleware for request id/logging where appropriate.
- Do not read env vars from controllers or orchestration services.
- Do not import provider SDK packages outside provider adapter modules.
## Code Smells To Fix
- provider-specific conditionals in controllers;
- repeated OpenAI error envelope construction;
- repeated config reference validation;
- raw secrets in logs or thrown errors;
- orchestration loops without hard backend limits;
- tests that only verify mocks were called;
- duplicated `AuthenticatedClient`-style shapes across services and request typings;
- provider payload casts without runtime validation;
- public or operational errors with misleading status/code semantics;
- abstractions named `Manager`, `Helper`, or `Util` without a clear domain role.
## Refactoring Rule
Refactor behind passing tests. If tests are missing, first add characterization tests for the behavior being preserved.
عرض على GitHub