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,105 @@
# Code Reuse Thinking Guide
> **Purpose**: Stop and think before creating new code - does it already exist?
---
## The Problem
**Duplicated code is the #1 source of inconsistency bugs.**
When you copy-paste or rewrite existing logic:
- Bug fixes don't propagate
- Behavior diverges over time
- Codebase becomes harder to understand
---
## Before Writing New Code
### Step 1: Search First
```bash
# Search for similar function names
grep -r "functionName" .
# Search for similar logic
grep -r "keyword" .
```
### Step 2: Ask These Questions
| Question | If Yes... |
|----------|-----------|
| Does a similar function exist? | Use or extend it |
| Is this pattern used elsewhere? | Follow the existing pattern |
| Could this be a shared utility? | Create it in the right place |
| Am I copying code from another file? | **STOP** - extract to shared |
---
## Common Duplication Patterns
### Pattern 1: Copy-Paste Functions
**Bad**: Copying a validation function to another file
**Good**: Extract to shared utilities, import where needed
### Pattern 2: Similar Components
**Bad**: Creating a new component that's 80% similar to existing
**Good**: Extend existing component with props/variants
### Pattern 3: Repeated Constants
**Bad**: Defining the same constant in multiple files
**Good**: Single source of truth, import everywhere
---
## When to Abstract
**Abstract when**:
- Same code appears 3+ times
- Logic is complex enough to have bugs
- Multiple people might need this
**Don't abstract when**:
- Only used once
- Trivial one-liner
- Abstraction would be more complex than duplication
---
## After Batch Modifications
When you've made similar changes to multiple files:
1. **Review**: Did you catch all instances?
2. **Search**: Run grep to find any missed
3. **Consider**: Should this be abstracted?
---
## Gotcha: Asymmetric Mechanisms Producing Same Output
**Problem**: When two different mechanisms must produce the same file set (e.g., recursive directory copy for init vs. manual `files.set()` for update), structural changes (renaming, moving, adding subdirectories) only propagate through the automatic mechanism. The manual one silently drifts.
**Symptom**: Init works perfectly, but update creates files at wrong paths or misses files entirely.
**Prevention checklist**:
- [ ] When migrating directory structures, search for ALL code paths that reference the old structure
- [ ] If one path is auto-derived (glob/copy) and another is manually listed, the manual one needs updating
- [ ] Add a regression test that compares outputs from both mechanisms
---
## Checklist Before Commit
- [ ] Searched for existing similar code
- [ ] No copy-pasted logic that should be shared
- [ ] Constants defined in one place
- [ ] Similar patterns follow same structure
@@ -0,0 +1,116 @@
# 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.
+79
View File
@@ -0,0 +1,79 @@
# Thinking Guides
> **Purpose**: Expand your thinking to catch things you might not have considered.
---
## Why Thinking Guides?
**Most bugs and tech debt come from "didn't think of that"**, not from lack of skill:
- Didn't think about what happens at layer boundaries → cross-layer bugs
- Didn't think about code patterns repeating → duplicated code everywhere
- Didn't think about edge cases → runtime errors
- Didn't think about future maintainers → unreadable code
These guides help you **ask the right questions before coding**.
---
## Available Guides
| Guide | Purpose | When to Use |
|-------|---------|-------------|
| [Code Reuse Thinking Guide](./code-reuse-thinking-guide.md) | Identify patterns and reduce duplication | When you notice repeated patterns |
| [Cross-Layer Thinking Guide](./cross-layer-thinking-guide.md) | Think through data flow across layers | Features spanning multiple layers |
---
## Quick Reference: Thinking Triggers
### When to Think About Cross-Layer Issues
- [ ] Feature touches 3+ layers (API, Service, Component, Database)
- [ ] Data format changes between layers
- [ ] Multiple consumers need the same data
- [ ] You're not sure where to put some logic
→ Read [Cross-Layer Thinking Guide](./cross-layer-thinking-guide.md)
### When to Think About Code Reuse
- [ ] You're writing similar code to something that exists
- [ ] You see the same pattern repeated 3+ times
- [ ] You're adding a new field to multiple places
- [ ] **You're modifying any constant or config**
- [ ] **You're creating a new utility/helper function** ← Search first!
→ Read [Code Reuse Thinking Guide](./code-reuse-thinking-guide.md)
---
## Pre-Modification Rule (CRITICAL)
> **Before changing ANY value, ALWAYS search first!**
```bash
# Search for the value you're about to change
grep -r "value_to_change" .
```
This single habit prevents most "forgot to update X" bugs.
---
## How to Use This Directory
1. **Before coding**: Skim the relevant thinking guide
2. **During coding**: If something feels repetitive or complex, check the guides
3. **After bugs**: Add new insights to the relevant guide (learn from mistakes)
---
## Contributing
Found a new "didn't think of that" moment? Add it to the relevant guide.
---
**Core Principle**: 30 minutes of thinking saves 3 hours of debugging.