chore: bootstrap trellis workspace and sync deployment settings
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Component Guidelines
|
||||
|
||||
> Widget composition and UI reuse conventions for `apps/lib/**`.
|
||||
|
||||
---
|
||||
|
||||
## Practical Conventions
|
||||
|
||||
1. Prefer shared widgets before creating new feature-local widgets.
|
||||
2. Use semantic theme slots (`Theme.of(context).colorScheme.*`) and project tokens (`AppSpacing`, `AppRadius`).
|
||||
3. Keep feature screens focused on composition; move reusable sections into `shared/widgets/**`.
|
||||
4. Use project-consistent feedback components (`Toast` / `AppBanner` / `AppLoadingIndicator`).
|
||||
|
||||
---
|
||||
|
||||
## Real File Path Examples
|
||||
|
||||
- Shared base components:
|
||||
- `apps/lib/shared/widgets/app_button.dart`
|
||||
- `apps/lib/shared/widgets/banner/app_banner.dart`
|
||||
- `apps/lib/shared/widgets/app_loading_indicator.dart`
|
||||
- Feature screen composition using shared widgets/tokens:
|
||||
- `apps/lib/features/auth/presentation/screens/login_screen.dart`
|
||||
- `apps/lib/features/settings/presentation/widgets/settings_page_scaffold.dart`
|
||||
- `apps/lib/features/home/presentation/widgets/home_composer_stack.dart`
|
||||
- Design system sources:
|
||||
- `apps/lib/core/theme/design_tokens.dart`
|
||||
- `apps/lib/core/theme/app_theme.dart`
|
||||
|
||||
---
|
||||
|
||||
## UI Contract Rules
|
||||
|
||||
1. **Color usage**
|
||||
- Use `colorScheme` for semantic colors.
|
||||
- Use `Theme.extension<AppColorPalette>()` only for brand palette/event/avatar domains.
|
||||
2. **Spacing & radius**
|
||||
- Use `AppSpacing.*` / `AppRadius.*` tokens as defaults.
|
||||
3. **Page actions & confirmations**
|
||||
- Reuse shared action/confirmation surfaces where available (for consistent interaction style).
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns (with evidence)
|
||||
|
||||
- Duplicating near-identical controls per feature instead of extending shared widgets.
|
||||
- Existing shared baseline in `apps/lib/shared/widgets/**` should be checked first.
|
||||
- Hardcoding user-facing feedback patterns outside project primitives.
|
||||
- Existing patterns: `AppBanner` in `login_screen.dart`, `AppLoadingIndicator` in `shared/widgets/app_loading_indicator.dart`.
|
||||
- Bypassing theme semantics by introducing ad-hoc `Colors.*` in feature widgets.
|
||||
- Current style source of truth is `apps/lib/core/theme/app_theme.dart` + `design_tokens.dart`.
|
||||
|
||||
---
|
||||
|
||||
## Uncertainties / Gaps
|
||||
|
||||
- There is no automated lint rule in this repo that forbids all hardcoded color constants in feature widgets; consistency relies on code review and AGENTS guidance.
|
||||
- Some older UI files may still contain local one-off style values where token extraction is incomplete.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Directory Structure
|
||||
|
||||
> How frontend (Flutter) code is organized in this repository.
|
||||
|
||||
---
|
||||
|
||||
## Practical Conventions
|
||||
|
||||
1. `apps/lib/main.dart` is the single root entry file.
|
||||
2. Keep second-level folders fixed to: `app/`, `core/`, `data/`, `features/`, `shared/`, `l10n/`.
|
||||
3. Put feature business code under `features/<feature>/...`; keep cross-feature infra/protocol in `core/` and shared infra in `data/`.
|
||||
4. Shared reusable UI belongs to `shared/widgets/**`, not duplicated under each feature.
|
||||
|
||||
---
|
||||
|
||||
## Real File Path Examples
|
||||
|
||||
- App bootstrap and routing composition:
|
||||
- `apps/lib/main.dart`
|
||||
- `apps/lib/app/app.dart`
|
||||
- `apps/lib/app/router/app_router.dart`
|
||||
- Shared infrastructure (non-feature business):
|
||||
- `apps/lib/data/network/api_client.dart`
|
||||
- `apps/lib/data/cache/cache_store.dart`
|
||||
- `apps/lib/core/theme/app_theme.dart`
|
||||
- Feature-bounded implementation:
|
||||
- `apps/lib/features/todo/data/apis/todo_api.dart`
|
||||
- `apps/lib/features/todo/data/repositories/todo_repository.dart`
|
||||
- `apps/lib/features/auth/presentation/bloc/auth_bloc.dart`
|
||||
|
||||
---
|
||||
|
||||
## Placement Checklist (before adding a file)
|
||||
|
||||
1. Does this logic belong to exactly one feature flow?
|
||||
- Yes -> `features/<feature>/...`
|
||||
2. Is it cross-feature protocol/orchestration (auth/session/notification/ui schema)?
|
||||
- Yes -> `core/**`
|
||||
3. Is it shared storage/network/cache infra?
|
||||
- Yes -> `data/**`
|
||||
4. Is it reusable widget/presentation helper with no feature business orchestration?
|
||||
- Yes -> `shared/widgets/**` (or `shared/forms/**`)
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns (with evidence)
|
||||
|
||||
- Creating feature business repositories/models under shared `apps/lib/data/**`.
|
||||
- Existing correct pattern is feature-local repositories under `apps/lib/features/**/data/repositories/`.
|
||||
- Letting UI code bypass repositories for consistency-sensitive data flow.
|
||||
- Correct references: `apps/lib/features/todo/data/repositories/todo_repository.dart`, `apps/lib/features/messages/data/repositories/inbox_repository.dart`.
|
||||
- Deep redundant nesting without clear ownership.
|
||||
- Current tree generally keeps flat-by-concern organization (e.g., `data/apis`, `data/repositories`, `presentation/screens`, `presentation/widgets`).
|
||||
|
||||
---
|
||||
|
||||
## Uncertainties / Gaps
|
||||
|
||||
- Some modules blend domain-specific and infrastructure concerns (for example, notification rewrite boundaries) and rely on AGENTS rules rather than strict automated folder enforcement.
|
||||
- No script currently validates folder placement rules automatically; enforcement is mostly review + convention.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Hook Guidelines (Bloc/Cubit State Flows)
|
||||
|
||||
> This repository is Flutter-based. This file defines state-flow conventions using Bloc/Cubit.
|
||||
|
||||
---
|
||||
|
||||
## Practical Conventions
|
||||
|
||||
1. Treat `AuthBloc` as the global auth source of truth; auth invalidation should flow through its event chain.
|
||||
2. Keep Cubit/Bloc states immutable and updated via `copyWith`.
|
||||
3. Catch-and-handle branches should log errors with module-scoped logger names.
|
||||
4. For async flow handoff (auth/session switch, SSE stream lifecycle), ensure race ordering is explicit (queues/epoch tokens/cancel semantics).
|
||||
|
||||
---
|
||||
|
||||
## Real File Path Examples
|
||||
|
||||
- Auth state source of truth and transitions:
|
||||
- `apps/lib/features/auth/presentation/bloc/auth_bloc.dart`
|
||||
- `apps/lib/features/auth/presentation/bloc/auth_event.dart`
|
||||
- `apps/lib/features/auth/presentation/bloc/auth_state.dart`
|
||||
- Feature-local form/interaction state:
|
||||
- `apps/lib/features/auth/presentation/cubits/login_cubit.dart`
|
||||
- `apps/lib/features/settings/presentation/cubits/automation_jobs_cubit.dart`
|
||||
- Multi-step async orchestration with explicit stream/session control:
|
||||
- `apps/lib/features/chat/presentation/bloc/chat_bloc.dart`
|
||||
- `apps/lib/core/chat/ag_ui_service.dart`
|
||||
- `apps/lib/app/app.dart`
|
||||
|
||||
---
|
||||
|
||||
## State-Flow Checklist
|
||||
|
||||
Before adding/changing state logic:
|
||||
|
||||
1. Is state ownership clear (global vs feature-local)?
|
||||
2. Are transitions serialized when order matters?
|
||||
3. Are recoverable failures surfaced to UI state and logged?
|
||||
4. Are side effects (cache reset, prewarm, SSE cancel/restart) bound to lifecycle events, not random UI callbacks?
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns (with evidence)
|
||||
|
||||
- Feature-level auth reset/navigation bypassing global auth flow.
|
||||
- Correct path: `ApiClient` auth-failure callback -> `AuthSessionInvalidated` event (`apps/lib/app/di/injection.dart`, `apps/lib/features/auth/presentation/bloc/auth_bloc.dart`).
|
||||
- Silent exception handling in async orchestration.
|
||||
- Existing weak branches to avoid copying:
|
||||
- `apps/lib/app/di/injection.dart` refresh callback catches and returns `false` without structured logging.
|
||||
- `apps/lib/core/chat/ag_ui_service.dart` ignores malformed SSE payload parsing errors by design.
|
||||
- Emitting mutable/partially-updated state objects.
|
||||
- Current state classes use immutable fields + `copyWith` (`LoginState`, `ChatState`, `AutomationJobsState`).
|
||||
|
||||
---
|
||||
|
||||
## Uncertainties / Gaps
|
||||
|
||||
- The codebase uses both Bloc and Cubit; exact selection criteria (when to pick Bloc vs Cubit) are not formally codified beyond existing patterns.
|
||||
- Some cancellation/retry branches return error strings directly (e.g., chat flow) and may need future standardization if UX/error taxonomy requirements tighten.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Frontend Development Guidelines (Flutter App)
|
||||
|
||||
> Scope: `apps/**` (Flutter mobile app). This index links to project-grounded guidelines only.
|
||||
|
||||
---
|
||||
|
||||
## Practical Conventions (Quick Rules)
|
||||
|
||||
1. Keep `apps/lib` second-level layout stable: `app/`, `core/`, `data/`, `features/`, `shared/`, `l10n/`.
|
||||
2. Use feature-bounded modules under `features/<domain>/...` and keep shared infra in `data/` + `core/`.
|
||||
3. Parse backend errors as RFC7807 (`code`/`params`) and keep mapping synced with protocol docs.
|
||||
4. Prefer shared UI widgets (`shared/widgets/**`) and design tokens (`AppSpacing`/`AppRadius` + `Theme.colorScheme`).
|
||||
|
||||
---
|
||||
|
||||
## Repository Evidence (entry files to read first)
|
||||
|
||||
- `apps/lib/main.dart` - bootstrap entry (`configureDependencies`, `Env.init`, `runApp`)
|
||||
- `apps/lib/app/app.dart` - app shell + theme + auth lifecycle orchestration
|
||||
- `apps/lib/app/di/injection.dart` - DI registration and cross-feature singleton wiring
|
||||
- `apps/AGENTS.md` - enforced frontend domain rules
|
||||
|
||||
## Real File Path Examples
|
||||
|
||||
- `apps/lib/main.dart`
|
||||
- `apps/lib/app/di/injection.dart`
|
||||
- `apps/lib/data/network/error_code_mapper.dart`
|
||||
|
||||
---
|
||||
|
||||
## Guidelines Index
|
||||
|
||||
| Guide | Focus |
|
||||
|---|---|
|
||||
| [Directory Structure](./directory-structure.md) | Module boundaries and placement rules |
|
||||
| [Component Guidelines](./component-guidelines.md) | Widget composition, shared components, design system usage |
|
||||
| [Hook Guidelines (Bloc/Cubit State Flows)](./hook-guidelines.md) | Flutter state flow conventions using Bloc/Cubit |
|
||||
| [Type Safety](./type-safety.md) | DTO parsing, API boundary typing, protocol alignment |
|
||||
| [Quality Guidelines](./quality-guidelines.md) | Lint/test/logging expectations and review checklist |
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns Observed (do not copy)
|
||||
|
||||
- Silent/weak failure branches still exist in some paths and should not be expanded:
|
||||
- `apps/lib/app/di/injection.dart` (`setRefreshCallback` catch branch returns `false` without logging)
|
||||
- `apps/lib/core/chat/ag_ui_service.dart` (malformed SSE payload catch branch intentionally ignores parse error)
|
||||
- Directly hardcoding API contract assumptions outside protocol docs/mappers leads to drift:
|
||||
- Keep `docs/protocols/common/http-error-codes.md` and `apps/lib/data/network/error_code_mapper.dart` synchronized.
|
||||
|
||||
---
|
||||
|
||||
## Uncertainties / Gaps
|
||||
|
||||
- The frontend workflow doc (`.trellis/workflow.md`) still uses the historical filename `hook-guidelines.md`; this index keeps the filename for compatibility while the content is Flutter Bloc/Cubit specific.
|
||||
- There is no repository-level automated check yet proving every protocol-code change updates all three sides (backend + protocol docs + frontend mapping); this is currently review-driven.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Quality Guidelines
|
||||
|
||||
> Frontend quality baseline for `apps/**` changes.
|
||||
|
||||
---
|
||||
|
||||
## Practical Conventions
|
||||
|
||||
1. Run Flutter analyzer/tests for touched scope before finalizing changes.
|
||||
2. Keep error logging explicit at catch sites using project logger (`getLogger(...)`).
|
||||
3. Prioritize regression tests for high-risk modules: auth/session, home viewport, cache/repository, agent SSE flows.
|
||||
4. Keep docs/protocol/frontend mappings aligned for API-contract changes.
|
||||
|
||||
---
|
||||
|
||||
## Real File Path Examples
|
||||
|
||||
- Lint/static analysis configuration:
|
||||
- `apps/analysis_options.yaml`
|
||||
- `apps/pubspec.yaml` (dev dependencies: `flutter_test`, `bloc_test`, `mocktail`)
|
||||
- Test suites for high-risk modules:
|
||||
- `apps/test/app/router/app_router_redirect_test.dart`
|
||||
- `apps/test/core/chat/ag_ui_service_test.dart`
|
||||
- `apps/test/data/cache/cached_repository_test.dart`
|
||||
- Logging usage examples:
|
||||
- `apps/lib/features/auth/presentation/bloc/auth_bloc.dart`
|
||||
- `apps/lib/features/auth/presentation/cubits/login_cubit.dart`
|
||||
- `apps/lib/features/settings/presentation/cubits/automation_jobs_cubit.dart`
|
||||
|
||||
---
|
||||
|
||||
## Review Checklist
|
||||
|
||||
1. **Layering and ownership**
|
||||
- No feature business logic moved into shared `data/**` infra.
|
||||
2. **Error handling**
|
||||
- Exceptions are either propagated or converted to typed user-safe errors.
|
||||
- Catch branches include context logging where actionable.
|
||||
3. **Contract alignment**
|
||||
- If API/error/event contracts changed, protocol docs and mapping updates are in the same change.
|
||||
4. **Regression coverage**
|
||||
- Add/adjust tests for changed behavior in critical flows.
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns (with evidence)
|
||||
|
||||
- Error swallowing branches that silently downgrade behavior.
|
||||
- Existing examples to avoid extending:
|
||||
- `apps/lib/app/di/injection.dart` refresh callback catch returns `false`.
|
||||
- `apps/lib/core/chat/ag_ui_service.dart` malformed SSE payload parse catch ignores payload.
|
||||
- Feature code bypassing shared feedback/loading primitives.
|
||||
- Project standard primitives exist in `apps/lib/shared/widgets/toast/`, `apps/lib/shared/widgets/banner/`, `apps/lib/shared/widgets/app_loading_indicator.dart`.
|
||||
- Protocol changes implemented only in one layer.
|
||||
- Contract source of truth is under `docs/protocols/**` and must stay synchronized.
|
||||
|
||||
---
|
||||
|
||||
## Uncertainties / Gaps
|
||||
|
||||
- The repository does not currently enforce all frontend rules via CI (for example, no strict automated checker for protocol-mapper parity).
|
||||
- `analysis_options.yaml` is currently close to Flutter defaults; stricter lint rules may still be introduced incrementally.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Type Safety
|
||||
|
||||
> API/data boundary typing and protocol alignment rules for Flutter frontend.
|
||||
|
||||
---
|
||||
|
||||
## Practical Conventions
|
||||
|
||||
1. Parse remote payloads into typed models at API/repository boundaries, not in UI widgets.
|
||||
2. Keep request/response key names aligned with backend/protocol snake_case fields.
|
||||
3. Parse backend errors as RFC7807 (`detail` + `code` + optional `params`) and map by `code` first.
|
||||
4. When protocol changes, update protocol docs and frontend mapping in the same change.
|
||||
|
||||
---
|
||||
|
||||
## Real File Path Examples
|
||||
|
||||
- Error transport parsing and localization mapping:
|
||||
- `apps/lib/data/network/api_exception.dart`
|
||||
- `apps/lib/data/network/error_code_mapper.dart`
|
||||
- `docs/protocols/common/http-error-codes.md`
|
||||
- Typed todo contract across frontend/backend/protocol:
|
||||
- `apps/lib/features/todo/data/apis/todo_api.dart`
|
||||
- `backend/src/v1/todo/schemas.py`
|
||||
- `docs/protocols/models/todo.md`
|
||||
- AG-UI/SSE contract consumption:
|
||||
- `apps/lib/core/chat/ag_ui_service.dart`
|
||||
- `apps/lib/features/chat/data/apis/chat_api_impl.dart`
|
||||
- `docs/protocols/agent/sse-events.md`
|
||||
|
||||
---
|
||||
|
||||
## Contract Checkpoints (frontend side)
|
||||
|
||||
1. Endpoint path + method alignment:
|
||||
- Example: `/api/v1/todos` in both `todo_api.dart` and backend `todo/router.py`.
|
||||
2. Field naming and shape alignment:
|
||||
- Example: `schedule_item_ids`, `created_at`, `updated_at` in todo DTOs.
|
||||
3. Error code alignment:
|
||||
- Any new backend `code` must be added to `http-error-codes.md` and `error_code_mapper.dart`.
|
||||
4. SSE lifecycle alignment:
|
||||
- Frontend stream handling expects terminal event (`RUN_FINISHED` or `RUN_ERROR`) per run.
|
||||
|
||||
---
|
||||
|
||||
## Anti-patterns (with evidence)
|
||||
|
||||
- Using free-text `detail` as the only user-facing error contract.
|
||||
- Correct implementation uses `code -> l10n key` mapping first in `api_exception.dart` + `error_code_mapper.dart`.
|
||||
- Parsing untyped `Map` payloads directly inside UI pages.
|
||||
- Current typed parsing is concentrated in API/model/repository files (e.g., `TodoResponse.fromJson`, `HistorySnapshot.fromJson`).
|
||||
- Changing backend error codes without frontend mapping update.
|
||||
- Registry and sync rule explicitly documented in `docs/protocols/common/http-error-codes.md`.
|
||||
|
||||
---
|
||||
|
||||
## Uncertainties / Gaps
|
||||
|
||||
- The repository currently has no automatic script that validates full parity between `http-error-codes.md` and `error_code_mapper.dart`.
|
||||
- Some API/model parsing remains manual (not fully generated), so contract drift risk is controlled mainly via tests/review.
|
||||
Reference in New Issue
Block a user