chore: bootstrap trellis workspace and sync deployment settings

This commit is contained in:
qzl
2026-04-20 17:15:50 +08:00
parent 0842e04c39
commit eeed737949
82 changed files with 16522 additions and 11 deletions
@@ -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.
+59
View File
@@ -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.
+56
View File
@@ -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.
+60
View File
@@ -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.