@pennixrv/trellis 0.7.0-beta.46 → 0.7.0-beta.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/workflow.js +1 -1
- package/dist/commands/workflow.js.map +1 -1
- package/dist/migrations/manifests/0.7.0-beta.47.json +9 -0
- package/dist/templates/codex/hooks/session-start.py +6 -6
- package/dist/templates/copilot/hooks/session-start.py +6 -6
- package/dist/templates/markdown/spec/backend/database-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/directory-structure.md.txt +20 -20
- package/dist/templates/markdown/spec/backend/error-handling.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/index.md.txt +19 -19
- package/dist/templates/markdown/spec/backend/logging-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/backend/quality-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/component-guidelines.md.txt +25 -25
- package/dist/templates/markdown/spec/frontend/directory-structure.md.txt +20 -20
- package/dist/templates/markdown/spec/frontend/hook-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/index.md.txt +20 -20
- package/dist/templates/markdown/spec/frontend/quality-guidelines.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/state-management.md.txt +22 -22
- package/dist/templates/markdown/spec/frontend/type-safety.md.txt +22 -22
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +80 -85
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +164 -209
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +161 -185
- package/dist/templates/markdown/spec/guides/index.md.txt +51 -51
- package/dist/templates/markdown/workspace-index.md +44 -44
- package/dist/templates/opencode/lib/session-utils.js +2 -2
- package/dist/templates/shared-hooks/session-start.py +7 -7
- package/dist/templates/trellis/scripts/add_session.py +35 -32
- package/dist/templates/trellis/scripts/common/developer.py +18 -18
- package/dist/templates/trellis/scripts/common/task_store.py +11 -11
- package/dist/templates/trellis/scripts/common/workflow_phase.py +4 -3
- package/dist/templates/trellis/workflow.md +403 -458
- package/package.json +2 -2
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
# Code Reuse Thinking Guide
|
|
1
|
+
# 代码复用思考指南(Code Reuse Thinking Guide)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **目的(Purpose)**:创建新代码前先停下来思考:它是否已经存在?
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## The Problem
|
|
7
|
+
## 问题(The Problem)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**重复代码是不一致错误的首要来源。**
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
11
|
+
复制粘贴或重写已有逻辑会导致:
|
|
12
|
+
- 错误修复无法传播
|
|
13
|
+
- 行为随时间逐渐分化
|
|
14
|
+
- 代码库更难理解
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
## Before Writing New Code
|
|
18
|
+
## 编写新代码前(Before Writing New Code)
|
|
19
19
|
|
|
20
|
-
### Step 1: Search First
|
|
20
|
+
### 第一步:先搜索(Step 1: Search First)
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
23
|
# Search for similar function names
|
|
@@ -27,50 +27,49 @@ grep -r "functionName" .
|
|
|
27
27
|
grep -r "keyword" .
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
### Step 2: Ask These Questions
|
|
30
|
+
### 第二步:回答这些问题(Step 2: Ask These Questions)
|
|
31
31
|
|
|
32
|
-
| Question | If Yes
|
|
32
|
+
| 问题(Question) | 如果是……(If Yes...) |
|
|
33
33
|
|----------|-----------|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
34
|
+
| 是否存在相似函数? | 使用或扩展它 |
|
|
35
|
+
| 其他地方是否使用了这种模式? | 遵循已有模式 |
|
|
36
|
+
| 它是否可以成为共享工具? | 在正确位置创建它 |
|
|
37
|
+
| 是否正在复制其他文件中的代码? | **停止**:提取为共享逻辑 |
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
## Common Duplication Patterns
|
|
41
|
+
## 常见重复模式(Common Duplication Patterns)
|
|
42
42
|
|
|
43
|
-
### Pattern 1: Copy-Paste Functions
|
|
43
|
+
### 模式一:复制粘贴函数(Pattern 1: Copy-Paste Functions)
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
**不佳**:将校验函数复制到另一个文件。
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
**较好**:提取为共享工具,在需要的位置导入。
|
|
48
48
|
|
|
49
|
-
### Pattern 2: Similar Components
|
|
49
|
+
### 模式二:相似组件(Pattern 2: Similar Components)
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
**不佳**:创建一个与现有组件有 80% 相似度的新组件。
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
**较好**:通过 props/变体扩展现有组件。
|
|
54
54
|
|
|
55
|
-
### Pattern 3: Repeated Constants
|
|
55
|
+
### 模式三:重复常量(Pattern 3: Repeated Constants)
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
**不佳**:在多个文件中定义同一个常量。
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
**较好**:保留唯一事实来源,在各处导入。
|
|
60
60
|
|
|
61
|
-
### Pattern 4: Repeated Payload Field Extraction
|
|
61
|
+
### 模式四:重复提取载荷字段(Pattern 4: Repeated Payload Field Extraction)
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
**错误示例(Bad)**:多个消费者各自在本地转换同一组 JSON/事件字段:
|
|
64
64
|
|
|
65
65
|
```typescript
|
|
66
66
|
const description = (ev as { description?: string }).description;
|
|
67
67
|
const context = (ev as { context?: ContextEntry[] }).context;
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
consumer now has its own definition of what a valid payload means.
|
|
70
|
+
即使只有两行代码,这也是重复的合同逻辑。此时每个消费者都有一份自己对“有效载荷”的定义。
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
**较好**:将解码器、类型守卫或投影放在数据 owner 旁边:
|
|
74
73
|
|
|
75
74
|
```typescript
|
|
76
75
|
if (isThreadEvent(ev)) {
|
|
@@ -78,37 +77,35 @@ if (isThreadEvent(ev)) {
|
|
|
78
77
|
}
|
|
79
78
|
```
|
|
80
79
|
|
|
81
|
-
|
|
82
|
-
shared type guard / normalizer / projection before adding a third reader.
|
|
80
|
+
**规则**:如果同一个无类型载荷字段在两个或更多位置被读取,在增加第三个读取者前创建共享类型守卫、规范化器或投影。
|
|
83
81
|
|
|
84
82
|
---
|
|
85
83
|
|
|
86
|
-
## When to Abstract
|
|
84
|
+
## 何时抽象(When to Abstract)
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
86
|
+
**在以下情况进行抽象**:
|
|
87
|
+
- 相同代码出现三次或更多
|
|
88
|
+
- 逻辑复杂到足以产生错误
|
|
89
|
+
- 多个人可能需要使用它
|
|
92
90
|
|
|
93
|
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
91
|
+
**在以下情况不要抽象**:
|
|
92
|
+
- 只使用一次
|
|
93
|
+
- 只是简单的一行代码
|
|
94
|
+
- 抽象后的复杂度高于重复代码
|
|
97
95
|
|
|
98
96
|
---
|
|
99
97
|
|
|
100
|
-
## After Batch Modifications
|
|
98
|
+
## 批量修改后(After Batch Modifications)
|
|
101
99
|
|
|
102
|
-
|
|
100
|
+
对多个文件进行相似修改后:
|
|
103
101
|
|
|
104
|
-
1.
|
|
105
|
-
2.
|
|
106
|
-
3.
|
|
102
|
+
1. **复核**:是否覆盖了所有实例?
|
|
103
|
+
2. **搜索**:运行 grep 查找遗漏
|
|
104
|
+
3. **考虑**:是否应该进行抽象?
|
|
107
105
|
|
|
108
|
-
### Reducers Should Use Exhaustive Structure
|
|
106
|
+
### Reducer 应使用穷举结构(Reducers Should Use Exhaustive Structure)
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
`phase`), prefer a reducer with one `switch` over scattered `if/else` updates.
|
|
108
|
+
当状态由类似 action 的值(`action`、`kind`、`status`、`phase`)派生时,优先使用一个 `switch` 的 reducer,而不是分散的 `if/else` 更新。
|
|
112
109
|
|
|
113
110
|
```typescript
|
|
114
111
|
// BAD - action-specific state transitions are hard to audit
|
|
@@ -127,30 +124,28 @@ switch (event.action) {
|
|
|
127
124
|
}
|
|
128
125
|
```
|
|
129
126
|
|
|
130
|
-
|
|
131
|
-
documented replay model; display code and commands should not duplicate pieces
|
|
132
|
-
of that replay model.
|
|
127
|
+
当事件日志是事实来源时,这一点尤其重要。Reducer 是有文档记录的重放模型;展示代码和命令不应重复该重放模型的局部逻辑。
|
|
133
128
|
|
|
134
129
|
---
|
|
135
130
|
|
|
136
|
-
## Checklist Before Commit
|
|
131
|
+
## 提交前清单(Checklist Before Commit)
|
|
137
132
|
|
|
138
|
-
- [ ]
|
|
139
|
-
- [ ]
|
|
140
|
-
- [ ]
|
|
141
|
-
- [ ]
|
|
142
|
-
- [ ]
|
|
143
|
-
- [ ] Reducer/action
|
|
133
|
+
- [ ] 已搜索现有相似代码
|
|
134
|
+
- [ ] 没有应当共享却被复制粘贴的逻辑
|
|
135
|
+
- [ ] 共享解码器之外没有重复提取无类型载荷字段
|
|
136
|
+
- [ ] 常量只在一个位置定义
|
|
137
|
+
- [ ] 相似模式遵循相同结构
|
|
138
|
+
- [ ] Reducer/action 转换集中在一个 reducer 或命令分发器中
|
|
144
139
|
|
|
145
140
|
---
|
|
146
141
|
|
|
147
|
-
## Gotcha: Python if/elif/else Exhaustive Check
|
|
142
|
+
## 注意:Python 的 if/elif/else 穷举检查(Gotcha: Python if/elif/else Exhaustive Check)
|
|
148
143
|
|
|
149
|
-
|
|
144
|
+
**问题**:Python 的 if/elif/else 链没有编译期穷举检查。向 `Literal` 类型(例如 `Platform`)增加新值时,已有 if/elif/else 链可能静默落入 `else`,使用错误的默认值。
|
|
150
145
|
|
|
151
|
-
|
|
146
|
+
**表现**:新平台只能部分工作,一些方法返回 Claude 默认值而不是平台专属值,并且不会抛出错误。
|
|
152
147
|
|
|
153
|
-
|
|
148
|
+
**示例**(`cli_adapter.py`):
|
|
154
149
|
```python
|
|
155
150
|
# BAD: "gemini" falls through to else, returns "claude"
|
|
156
151
|
@property
|
|
@@ -171,53 +166,53 @@ def cli_name(self) -> str:
|
|
|
171
166
|
return "claude"
|
|
172
167
|
```
|
|
173
168
|
|
|
174
|
-
|
|
169
|
+
**预防**:向 Python `Literal` 类型增加新值时,搜索所有基于该类型分支的 if/elif/else 链,并增加显式分支。不要假定 `else` 对新值仍然正确。
|
|
175
170
|
|
|
176
171
|
---
|
|
177
172
|
|
|
178
|
-
## Gotcha: Asymmetric Mechanisms Producing Same Output
|
|
173
|
+
## 注意:产生相同输出的非对称机制(Gotcha: Asymmetric Mechanisms Producing Same Output)
|
|
179
174
|
|
|
180
|
-
|
|
175
|
+
**问题**:当两个不同机制必须产生相同文件集合时(例如 init 的递归目录复制与 update 的手动 `files.set()`),结构变化(重命名、移动、增加子目录)只会通过自动机制传播,手动机制会静默漂移。
|
|
181
176
|
|
|
182
|
-
|
|
177
|
+
**表现**:init 完全正常,但 update 将文件创建到错误路径,或完全遗漏文件。
|
|
183
178
|
|
|
184
|
-
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
179
|
+
**预防**:
|
|
180
|
+
- **最佳做法**:消除非对称性,让手动路径调用自动路径(例如让 `collectTemplateFiles()` 调用 `getAllScripts()`,而不是维护自己的列表)。
|
|
181
|
+
- **如果无法避免非对称性**:增加回归测试,比较两种机制的输出。
|
|
182
|
+
- 迁移目录结构时,搜索所有引用旧结构的代码路径。
|
|
188
183
|
|
|
189
|
-
|
|
184
|
+
**真实示例**:`trellis update` 曾为 11 个脚本维护手动 `files.set()` 列表,而 `getAllScripts()` 已经跟踪这些脚本。修复方式是用 `for..of getAllScripts()` 循环替换手动列表。参见 v0.4.0-beta.3 的 `update.ts` 重构。
|
|
190
185
|
|
|
191
186
|
---
|
|
192
187
|
|
|
193
|
-
##
|
|
188
|
+
## 模板文件登记(Trellis-specific)
|
|
194
189
|
|
|
195
|
-
|
|
190
|
+
向 `src/templates/trellis/scripts/` 增加文件时:
|
|
196
191
|
|
|
197
|
-
|
|
192
|
+
**唯一登记点**:`src/templates/trellis/index.ts`
|
|
198
193
|
|
|
199
|
-
1.
|
|
200
|
-
2.
|
|
194
|
+
1. 增加 `export const xxxScript = readTemplate("scripts/path/file.py");`
|
|
195
|
+
2. 加入 `getAllScripts()` Map。
|
|
201
196
|
|
|
202
|
-
|
|
197
|
+
完成这两步即可。`commands/update.ts` 直接使用 `getAllScripts()`,不需要手动同步列表。
|
|
203
198
|
|
|
204
|
-
|
|
199
|
+
**原因**:如果没有在 `getAllScripts()` 中登记,`trellis update` 就不会把文件同步到用户项目,错误修复和新功能也无法传播。
|
|
205
200
|
|
|
206
|
-
|
|
201
|
+
**历史**:在 v0.4.0-beta.3 之前,`update.ts` 有一份自己维护的文件列表,经常与 `getAllScripts()` 不同步,导致 `trellis update` 静默跳过 11 个 Python 文件。修复方式是删除重复列表,并将 `getAllScripts()` 作为唯一事实来源。
|
|
207
202
|
|
|
208
|
-
### Quick Checklist for New Scripts
|
|
203
|
+
### 新增脚本快速清单(Quick Checklist for New Scripts)
|
|
209
204
|
|
|
210
205
|
```bash
|
|
211
206
|
# After adding a new .py file, verify it's in getAllScripts():
|
|
212
207
|
grep -l "newFileName" src/templates/trellis/index.ts # Should match
|
|
213
208
|
```
|
|
214
209
|
|
|
215
|
-
### Template Sync Convention
|
|
210
|
+
### 模板同步约定(Template Sync Convention)
|
|
216
211
|
|
|
217
|
-
`.trellis/scripts
|
|
212
|
+
`.trellis/scripts/`(自用代码)与 `packages/cli/src/templates/trellis/scripts/`(模板)必须保持一致。编辑 `.trellis/scripts/` 后始终同步:
|
|
218
213
|
|
|
219
214
|
```bash
|
|
220
215
|
rsync -av --delete --exclude='__pycache__' .trellis/scripts/ packages/cli/src/templates/trellis/scripts/
|
|
221
216
|
```
|
|
222
217
|
|
|
223
|
-
|
|
218
|
+
**注意**:使用错误的 rsync 源路径或目标路径可能创建嵌套的垃圾目录(例如 `.trellis/scripts/packages/cli/...`)。运行前始终复核路径。
|