clean-architecturelisted
Install: claude install-skill ghozimahdi/gm-aiagent-plugins
Resolve `UFIL_ROOT` to the plugin root containing this skill. Claude Code may
provide `CLAUDE_PLUGIN_ROOT`; Codex can resolve it from the installed skill
path.
## Clean Architecture Patterns (GM Standard)
### Layer Rules
- **Presentation → Domain → Data** flow only. Never access data layer from presentation.
- Domain layer has NO dependencies on data or presentation.
- Presentation uses UseCases, never imports from data layer directly.
- **Pages MUST NOT call UseCases directly.** Only Blocs depend on UseCases — pages depend on Blocs. UseCases are injected into the Bloc via the constructor (`@injectable` Bloc + `@lazySingleton` UseCase). Pages dispatch events with `context.read<TBloc>().add(...)` and read state with `BlocBuilder`/`BlocConsumer`/`BlocSelector`/`BlocListener`. A page that imports a UseCase or calls `getIt<XUseCase>()` is ALWAYS wrong, even for one-shot ops like logout/refresh/delete — there is NO "too simple to need a bloc" exception.
### Model (Domain) — `@freezed` + `@Default`, NO nullable
```dart
@freezed
sealed class TenantModel with _$TenantModel {
const factory TenantModel({
@Default('') String id,
@Default('') String name,
@Default('') String phone,
}) = _TenantModel;
}
```
### DTO (Data) — `@freezed` + nullable + `@JsonKey`, NO `.toModel()`
```dart
@freezed
abstract class TenantDto with _$TenantDto {
const factory TenantDto({
@JsonKey(name: 'id') String? id,
@JsonKey(name: 'name') String? name,
@JsonKey(name: 'phone_n