Files

117 lines
4.9 KiB
Markdown
Raw Permalink Normal View History

# Cross-Layer Thinking Guide
> Purpose: prevent contract drift across `docs/protocols` -> backend -> frontend.
---
## Practical Conventions
1. Treat `docs/protocols/**` as the contract source of truth before code changes.
2. For any API/event/error contract change, verify all three sides in one pass:
- Protocol doc
- Backend transport/output
- Frontend parsing/mapping
3. Prefer explicit boundary checks over implicit assumptions (status/code/date/run lifecycle).
4. When touching cross-layer behavior, keep a short written checkpoint list in task notes (aligned with `.opencode/commands/trellis/finish-work.md` cross-layer verification items).
---
## Project-Specific Boundary Map
| Boundary | Contract Source | Backend Evidence | Frontend Evidence |
|---|---|---|---|
| HTTP errors | `docs/protocols/common/http-error-codes.md` | `backend/src/core/http/response.py`, `backend/src/app.py` | `apps/lib/data/network/api_exception.dart`, `apps/lib/data/network/error_code_mapper.dart` |
| Todo model | `docs/protocols/models/todo.md` | `backend/src/v1/todo/schemas.py`, `backend/src/v1/todo/router.py` | `apps/lib/features/todo/data/apis/todo_api.dart` |
| Agent SSE events | `docs/protocols/agent/sse-events.md` | `backend/src/v1/agent/router.py` | `apps/lib/features/chat/data/apis/chat_api_impl.dart`, `apps/lib/core/chat/ag_ui_service.dart` |
## Real File Path Examples
- `docs/protocols/common/http-error-codes.md`
- `backend/src/v1/agent/router.py`
- `apps/lib/core/chat/ag_ui_service.dart`
---
## Contract Checkpoints (Required for cross-layer work)
### 1) Endpoint and payload shape
- Confirm method/path/query/body on both sides.
- Example pair:
- Backend: `backend/src/v1/todo/router.py` (`/api/v1/todos`, query `status/priority`)
- Frontend: `apps/lib/features/todo/data/apis/todo_api.dart` (`getTodos`, `createTodo`, `reorderTodos`)
### 2) Error code transport and mapping
- Backend should return RFC7807 + stable `code`/`params`.
- Frontend should localize by `code`, not by free-text `detail`.
- Example triplet:
- `docs/protocols/common/http-error-codes.md`
- `backend/src/core/http/response.py`
- `apps/lib/data/network/error_code_mapper.dart`
### 3) Event lifecycle completeness (SSE)
- Ensure lifecycle expectations are symmetric:
- backend stream semantics (filter + terminal event)
- frontend stream completion/recovery logic
- Example pair:
- `backend/src/v1/agent/router.py` (target run filtering, terminal events)
- `apps/lib/core/chat/ag_ui_service.dart` (terminal event required for stream completion)
### 4) Date/time and ID boundary parsing
- Check datetime serialization/parsing and UUID/string assumptions across layers.
- Example:
- `backend/src/v1/todo/schemas.py` (`datetime`, `UUID`)
- `apps/lib/features/todo/data/apis/todo_api.dart` (`DateTime.parse`, string IDs)
---
## Project Examples
### Example A: Todo contract alignment
1. Protocol defines field names and ordering rules: `docs/protocols/models/todo.md`
2. Backend enforces schema and route behavior: `backend/src/v1/todo/schemas.py`, `backend/src/v1/todo/router.py`
3. Frontend maps to model parsing and request payloads: `apps/lib/features/todo/data/apis/todo_api.dart`
Checklist:
- [ ] field names (`schedule_item_ids`, `created_at`, `updated_at`) match
- [ ] enums/ranges (`status`, `priority`) match
- [ ] reorder payload shape (`items: [{id, priority, order}]`) matches
### Example B: Agent SSE run lifecycle alignment
1. Protocol lifecycle doc: `docs/protocols/agent/sse-events.md`
2. Backend stream filtering/termination: `backend/src/v1/agent/router.py`
3. Frontend consumption/recovery: `apps/lib/core/chat/ag_ui_service.dart`
Checklist:
- [ ] frontend sends `runId` query for `/events`
- [ ] backend only emits target run to subscriber
- [ ] frontend treats `RUN_FINISHED`/`RUN_ERROR` as terminal for stream completion
---
## Anti-patterns (with current evidence)
- Changing backend error codes without updating protocol registry and frontend mapper.
- Synchronization points: `http-error-codes.md` + `error_code_mapper.dart`.
- Inferring user-facing behavior from `detail` free text.
- Frontend already supports code-first mapping in `api_exception.dart`; bypassing this creates localization drift.
- Swallowing boundary failures in stream/auth paths.
- Existing weak branches (do not extend):
- `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
- `backend/src/v1/agent/router.py` SSE slot acquire/release failure falls back to warning + continue
---
## Uncertainties / Gaps
- No repository-wide automated checker currently validates full cross-layer parity (protocol doc <-> backend implementation <-> frontend mapping/event consumer).
- Some fallback branches exist for runtime resilience in legacy paths; whether to hard-fail vs degrade is not yet uniformly specified across all modules.