flower-trellis 0.2.4 → 0.2.5-beta.2

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.
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  name: trellis-push
3
- description: "Commit + push across configured repos with optional merge-to-target."
3
+ description: "提交并推送配置仓库,可选合并到目标分支,并同步任务进度快照。"
4
4
  ---
5
5
  # Push — 提交并推送(可选合并到目标分支)
6
6
 
7
- 一键完成 commit → push → 可选 merge 到目标分支(通常是测试线)→ push 目标分支切回。
7
+ 一键完成 commit → push → 可选 merge 到目标分支 写入任务进度快照输出结果。
8
8
 
9
- 支持多仓库(frontend / backend),merge 目标分支记录在 `.trellis/config.yaml` `packages.<name>.merge_target` 中。
9
+ 核心原则:**先计划、一次确认、后执行**。在任何 `git add`、`git commit`、`git push`、`git merge` 之前,必须先展示完整执行计划,并获得用户确认。
10
+
11
+ 支持多仓库(frontend / backend 等),merge 目标分支记录在 `.trellis/config.yaml` 的 `packages.<name>.merge_target` 中。
10
12
 
11
13
  ---
12
14
 
@@ -19,236 +21,350 @@ packages:
19
21
  frontend:
20
22
  path: iqs-front-human
21
23
  git: true
22
- merge_target: test # 首次 push 时询问后自动写入
24
+ merge_target: test # 首次指定后可回写
23
25
  backend:
24
26
  path: iqs
25
27
  git: true
26
28
  merge_target: test
27
29
  ```
28
30
 
29
- > 首次运行时如果 `merge_target` 不存在,会在 merge 步骤询问目标分支并回写到 `config.yaml`。
30
- > 如需修改,直接编辑 `config.yaml` 或通过 `/trellis-push` 传入 `--reconfigure` 语义。
31
+ > 首次运行时如果 `merge_target` 不存在,默认跳过 merge;如果用户在统一执行计划中明确指定目标分支,可将其回写到 `config.yaml`。如需修改,直接编辑 `config.yaml` 或通过 `/trellis-push` 传入 `--reconfigure` 语义。
32
+
33
+ ---
34
+
35
+ ## 总流程
36
+
37
+ ```text
38
+ Step 0 读取配置、模式与活动任务上下文
39
+ Step 1 预检并收集所有候选仓库状态
40
+ Step 2 生成统一执行计划(业务提交 + push/merge + snapshot + 父仓 bookkeeping)
41
+ Step 3 用户确认后执行业务仓库 commit / push
42
+ Step 4 按已确认计划执行可选 merge
43
+ Step 5 写入已确认的任务进度快照,并补齐运行后字段
44
+ Step 6 输出结果
45
+ ```
46
+
47
+ 除非出现“计划变化、执行失败重试、用户调整 snapshot、父仓出现额外 dirty 文件、merge 冲突”等情况,否则不要在执行中途追加新的确认问题。
31
48
 
32
49
  ---
33
50
 
34
- ## 执行步骤
51
+ ## Step 0: 读取配置、模式与活动任务上下文
52
+
53
+ ### 0.1 解析语义模式
54
+
55
+ 支持自然语言或 skill args 传入:
56
+
57
+ | 语义 | 说明 | 用户怎么说 |
58
+ |------|------|-----------|
59
+ | 默认 | 自动检测所有有变更的仓库并处理 | `/trellis-push` |
60
+ | commit-only | 只 commit 不 push,跳过 push / merge | `只提交不推` / `commit-only` |
61
+ | 指定仓库 | 只处理指定仓库 | `只 push 前端` / `push frontend` |
62
+ | 重新配置 | 本次允许重新指定 merge 目标,并回写 `merge_target` | `重新配置 push 目标分支` / `reconfigure push` |
63
+ | 临时目标 | 本次临时指定 merge 目标,不修改配置 | `push 到 hotfix 分支` |
64
+ | snapshot-only | 不提交业务代码,只写入 / 同步任务进度快照 | `只更新 snapshot` / `snapshot-only` |
65
+
66
+ `snapshot-only` 只在用户明确要求时使用。它仍必须展示统一执行计划;`pushed_commits` 取计划中确认的现有 commit,或按用户说明记录。
67
+
68
+ ### 0.2 发现候选 Git 仓库
35
69
 
36
- ### Step 0: 读取配置
70
+ 读取 `.trellis/config.yaml` 中的 `packages` 配置,但不要把 `git: true` 当作唯一仓库发现规则。`git: true` 主要用于 Trellis session context 展示独立包仓库状态;`trellis-push` 必须以实际 Git root 为准发现可提交仓库:
37
71
 
38
- 读取 `.trellis/config.yaml` 中的 `packages` 配置,识别所有 `git: true` 的仓库及其 `merge_target`(如果已配置)。
72
+ - **父仓根目录(含 `.trellis/` 的项目根)始终作为一个候选仓库**,即使它没有配置 `git: true`。
73
+ - packages 中配置的路径如果自身是独立 Git root(存在 `.git` 目录或 submodule 的 `.git` 文件),也作为候选仓库。
74
+ - 如果 package 路径位于父仓内部但不是独立 Git root,不要把它当作单独仓库;它的变更归父仓候选项处理。
75
+ - 如果用户指定了仓库,只保留匹配的候选项;指定父仓可用 `root`、`parent`、`main repo` 或默认 package 名。
76
+ - 同一个 Git root 只保留一次,避免 `path: .` 与父仓重复。
39
77
 
40
- ### Step 0.5: 读取活动任务上下文(可选)
78
+ merge 目标仍从对应 package 的 `merge_target` 读取;父仓没有 package 配置时,默认不设置 merge 目标。
41
79
 
42
- 为后续 Step 3「写入任务进度快照」准备输入。本步骤**不阻塞**主流程:任何读取失败都按"无任务上下文"继续,不要中断 push。
80
+ ### 0.3 读取活动任务上下文(可选)
81
+
82
+ 为生成 snapshot 草案准备输入。本步骤**不阻塞**主流程:任何读取失败都按“无任务上下文”继续,不要中断 push。
43
83
 
44
84
  ```bash
45
85
  # 在仓库根目录(含 .trellis/ 的项目根,不是 package 子目录)
46
86
  python3 ./.trellis/scripts/task.py current
47
87
  ```
48
88
 
49
- - **无活动任务**(命令退出码非 0 或输出为空):在内存里标记 `active_task=None`,**跳过 Step 3**,把本次 push 当作纯 chore push 处理。
50
- - **有活动任务**:解析输出拿到 task 路径(形如 `.trellis/tasks/MM-DD-name/`),并读取下列内容供 Step 3 使用:
89
+ - **无活动任务**(命令退出码非 0 或输出为空):在计划中标记 `snapshot: 跳过(无活动任务)`。
90
+ - **有活动任务**:解析输出拿到 task 路径(形如 `.trellis/tasks/MM-DD-name/`),并读取下列内容:
51
91
  - `<task_dir>/implement.md`(如有)— 步骤清单,AI 推断进度的主依据
52
92
  - `<task_dir>/task.json` 的 `last_push_snapshot` 字段(如有)— 上次推送时的进度基线
53
- - `<task_dir>/task.json` 的 `base_branch` 字段 — 用于 `git log <base_branch>..HEAD` 圈定本任务的 commit 范围
93
+ - `<task_dir>/task.json` 的 `base_branch` 字段 — 用于 `git log <base_branch>..HEAD` 圈定本任务 commit 范围
54
94
 
55
- > 本步骤只读不写。如果读取异常(task.json 损坏、implement.md 缺失等),Step 3 退化为"完全靠用户口述进度",不影响 push 主流程。
95
+ ---
56
96
 
57
- ### Step 1: 检测变更
97
+ ## Step 1: 预检并收集仓库状态
58
98
 
59
- 读取 `.trellis/config.yaml` 中的 `packages` 配置,对每个 git 仓库检测变更:
99
+ 对每个候选 Git 仓库收集:
60
100
 
61
101
  ```bash
62
- # 对每个 package
63
102
  cd <package_path>
64
103
  git status --short
104
+ git branch --show-current
105
+ git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null || true
106
+ git diff --stat
107
+ git diff --name-only
108
+ git log --oneline -5
65
109
  ```
66
110
 
67
- 列出有变更的仓库。如果所有仓库都没有变更,提示用户并终止。
111
+ 如果有活动任务和 `base_branch`,再收集:
68
112
 
69
- 如果只有部分仓库有变更,只处理有变更的仓库。
113
+ ```bash
114
+ git log <base_branch>..HEAD --oneline
115
+ ```
70
116
 
71
- ### Step 2: 逐仓库处理
117
+ 预检规则:
72
118
 
73
- 对每个有变更的仓库,依次执行以下操作:
119
+ - 所有候选仓库都无变更,且不是 `snapshot-only`:提示用户并终止。
120
+ - 有未合并状态、rebase 状态或 merge 冲突残留:立即停止,展示状态;不要继续生成执行计划。
121
+ - 当前分支为空、detached HEAD、或无法确认分支:停止并说明原因。
122
+ - dirty 文件必须按来源分组:**AI 本轮编辑** 与 **未识别 dirty 文件**。未识别 dirty 文件默认不纳入提交计划。
123
+ - 如果父仓(含 `.trellis/` 的仓库)后续要写 snapshot,先记录父仓当前 `git status --short`,供 Step 5 判断是否有额外 dirty 文件。
74
124
 
75
- > **commit-only 模式**(调用方传入「只提交不推」/「commit-only」语义,如 Trellis Phase 3.4「commit now, push later」):只执行 2.1 展示 → 2.2 暂存确认 → 2.3 commit,**跳过 2.4 push 与 2.5 merge**。Step 3 快照、Step 4 结果照常,结果中标注「本地已提交、未推送,后续仍走 trellis-push 推」。
125
+ ---
76
126
 
77
- #### 2.1 展示变更摘要
127
+ ## Step 2: 生成统一执行计划
78
128
 
79
- ```bash
80
- cd <package_path>
81
- git diff --stat
82
- git diff --name-only
129
+ 这是唯一的常规确认点。**确认前禁止执行任何 `git add` / commit / push / merge / task.json 写入。**
130
+
131
+ ### 2.1 生成业务提交计划
132
+
133
+ 对每个有变更的仓库生成:
134
+
135
+ - 仓库名、路径、当前分支、上游分支
136
+ - AI 本轮编辑且拟纳入提交的具体文件列表
137
+ - 未识别 dirty 文件列表(默认不纳入提交)
138
+ - 用户明确要求纳入的未识别文件列表(如有)
139
+ - 草拟 commit message
140
+ - push 计划(默认 / commit-only / 已有 upstream / 需要 `-u`)
141
+ - merge 计划(跳过 / 合并到配置目标 / 合并到临时目标 / 重新配置后回写)
142
+
143
+ commit message 生成规则:
144
+
145
+ - 读取最近 5 条 commit 参考风格。
146
+ - 类型前缀使用 `feat` / `fix` / `docs` / `chore` / `refactor` 等。
147
+ - 简短描述变更内容。
148
+ - 默认使用中文描述,除非项目历史明显使用英文。
149
+
150
+ ### 2.2 生成 snapshot 草案
151
+
152
+ 仅当有活动任务,或用户明确要求 `snapshot-only` 时生成。snapshot 的语义内容并入统一确认,不再默认二次询问。
153
+
154
+ 收集信号:
155
+
156
+ - `implement.md` 步骤清单(如缺失,则说明推断依据不足)
157
+ - 各仓库 `git log <base_branch>..HEAD --oneline`
158
+ - 上次 `last_push_snapshot`(如有)
159
+ - 本次业务提交计划中的变更内容
160
+
161
+ 计划中展示:
162
+
163
+ ```markdown
164
+ 任务进度快照计划:
165
+ - task: <task_dir>
166
+ - completed_steps: ["Step 1", "Step 2"]
167
+ - partial_step: "Step 3(如有)"
168
+ - next_step: "Step 4(如有)"
169
+ - notes: "<可选说明>"
170
+ - branch: 执行成功后按实际分支补齐
171
+ - pushed_commits: 执行成功后按实际 commit hash 补齐
172
+ - snapshot_at: 执行成功后写入当前 ISO 8601 时间
173
+ - bookkeeping: 只提交 `<task_dir>/task.json`
174
+ ```
175
+
176
+ 字段语义保持兼容:
177
+
178
+ ```json
179
+ "last_push_snapshot": {
180
+ "snapshot_at": "<ISO 8601 时间戳>",
181
+ "branch": "<任务分支名,或多仓字典>",
182
+ "pushed_commits": {
183
+ "frontend": "abc1234",
184
+ "backend": "def5678"
185
+ },
186
+ "completed_steps": ["Step 1", "Step 2"],
187
+ "partial_step": "Step 3(可选)",
188
+ "next_step": "Step 4(可选)",
189
+ "notes": "可选说明"
190
+ }
83
191
  ```
84
192
 
85
- #### 2.2 暂存文件
193
+ > `pushed_commits`、`snapshot_at`、实际 branch / commit hash 是运行后字段。用户确认的是 snapshot 的语义内容和写入动作;执行成功后由 AI 按实际结果补齐。
194
+
195
+ commit-only 模式下,字段名仍保持 `pushed_commits` 以兼容恢复逻辑;值记录本次生成的本地 commit hash,并在 `notes` 中注明“commit-only:本地已提交,未推送”。
196
+
197
+ ### 2.3 展示确认模板
198
+
199
+ 使用以下格式向用户展示完整计划:
200
+
201
+ ```markdown
202
+ ## trellis-push 执行计划
203
+
204
+ 模式:<默认 / commit-only / snapshot-only / 指定仓库 / reconfigure / 临时目标>
205
+
206
+ ### 业务仓库
207
+
208
+ 1. <package> (`<path>`)
209
+ - 分支:<current_branch> -> <upstream 或 origin/current_branch>
210
+ - AI 本轮编辑,拟提交:
211
+ - <file-a>
212
+ - <file-b>
213
+ - 未识别 dirty,默认不提交:
214
+ - <unknown-file 或 无>
215
+ - 用户要求纳入的未识别文件:
216
+ - <file 或 无>
217
+ - commit message:`<type>(<scope>): <description>`
218
+ - push:<执行 / 跳过(commit-only)>
219
+ - merge:<跳过 / 合并到 target / 临时合并到 target / 重新配置为 target>
220
+
221
+ ### 任务快照
222
+
223
+ - <跳过原因,或 snapshot 草案>
224
+
225
+ ### 父仓 bookkeeping
86
226
 
87
- 展示要暂存的文件列表,**获得用户确认后**再暂存。
227
+ - <跳过原因,或仅提交 `<task_dir>/task.json`>
228
+
229
+ 确认后将按上述计划执行。回复 `ok` / `行` / `确认` 执行;回复 `skip snapshot` 跳过快照;回复修改意见则先更新计划;回复 `manual` / `我自己来` 则停止。
230
+ ```
231
+
232
+ 确认规则:
233
+
234
+ - 用户确认前不得暂存。
235
+ - 用户修改 commit message、merge 目标或 snapshot 草案时,更新计划并重新展示确认。
236
+ - 用户要求纳入未识别 dirty 文件时,必须明确列出这些文件后重新确认。
237
+ - 用户拒绝文件范围或选择手动处理时,立即停止,不执行任何 git 写操作。
238
+
239
+ ---
240
+
241
+ ## Step 3: 按计划执行业务 commit / push
242
+
243
+ 确认后,对每个业务仓库按计划执行。
244
+
245
+ ### 3.1 执行前复核
246
+
247
+ 执行前重新运行:
88
248
 
89
249
  ```bash
90
- git add <具体文件列表>
250
+ git status --short
251
+ git diff --name-only
91
252
  ```
92
253
 
93
- > **[!] 禁止使用 `git add -A` 或 `git add .`**
94
- > 必须明确列出文件,避免误提交敏感文件(.env、credentials 等)。
254
+ 如果文件状态与确认计划不一致,停止并说明“计划已变化,需要重新确认”。不要临时扩展提交范围。
95
255
 
96
- #### 2.3 生成 commit message 并提交
256
+ ### 3.2 暂存与提交
97
257
 
98
- 分析变更内容,生成符合项目风格的 commit message:
99
- - 读取最近 5 条 commit 参考风格
100
- - 类型前缀:`feat` / `fix` / `chore` / `refactor` 等
101
- - 简短描述变更内容
102
- - 使用中文描述
258
+ 只暂存计划中明确列出的文件:
103
259
 
104
260
  ```bash
261
+ git add <具体文件列表>
105
262
  git commit -m "<type>(<scope>): <description>"
106
263
  ```
107
264
 
108
- #### 2.4 Push 当前分支
265
+ 禁止:
266
+
267
+ - `git add -A`
268
+ - `git add .`
269
+ - 暂存确认计划之外的文件
270
+ - 未经确认修改 commit message
109
271
 
110
- > **commit-only 模式:跳过 2.4 2.5**,直接进 Step 3。
272
+ ### 3.3 Push 当前分支
273
+
274
+ commit-only 模式跳过本节。
111
275
 
112
276
  ```bash
113
277
  git push origin <current_branch>
114
278
  ```
115
279
 
116
- 如果远程没有该分支,使用 `-u` 建立跟踪:
280
+ 如果远程没有该分支,且计划已说明需要建立 upstream:
117
281
 
118
282
  ```bash
119
283
  git push -u origin <current_branch>
120
284
  ```
121
285
 
122
- #### 2.5 询问是否 Merge 到目标分支(可选)
123
-
124
- Push 完成后,检查该 package 是否已配置 `merge_target`:
286
+ push 失败时立即停止,展示失败原因和已完成仓库状态。不要自动 force push。
125
287
 
126
- **已配置 `merge_target`**:
127
-
128
- ```markdown
129
- <package> 已推送到 <current_branch>。是否合并到 <merge_target>?
288
+ ---
130
289
 
131
- 1. 是,合并到 <merge_target>
132
- 2. 否,跳过
133
- ```
290
+ ## Step 4: 按计划执行可选 merge
134
291
 
135
- **未配置 `merge_target`(首次)**:
292
+ 只有在统一执行计划中明确写了 merge 目标时才执行。不要在 push 后临时追问是否 merge。
136
293
 
137
- ```markdown
138
- <package> 已推送到 <current_branch>。是否需要合并到其他分支(如测试线)?
294
+ 执行前再次确认当前工作区干净:
139
295
 
140
- 1. 是,请输入目标分支名
141
- 2. 否,跳过
296
+ ```bash
297
+ git status --short
142
298
  ```
143
299
 
144
- 如果用户输入了目标分支名,**将其回写到 `.trellis/config.yaml`** 对应 package 的 `merge_target` 字段,下次自动使用。
300
+ 如果不干净,停止并说明原因。
145
301
 
146
- **如果用户选择合并**:
302
+ 按计划执行:
147
303
 
148
304
  ```bash
149
- # 切换到目标分支并拉取最新
150
305
  git checkout <target_branch>
151
306
  git pull origin <target_branch>
152
-
153
- # 合并当前开发分支
154
307
  git merge <current_branch> --no-edit
155
-
156
- # Push 目标分支
157
308
  git push origin <target_branch>
158
-
159
- # 切回开发分支
160
309
  git checkout <current_branch>
161
310
  ```
162
311
 
163
- > **[!] 如果 merge 出现冲突:**
164
- > 1. 立即停止,展示冲突文件列表
165
- > 2. 询问用户:手动解决 / 中止 merge
166
- > 3. **绝对不能** `git merge --abort` 后静默跳过
312
+ 如果 merge 目标是 `main` / `master`,计划中必须已经包含额外警告和用户确认。
167
313
 
168
- **如果用户选择跳过**:直接进入下一个仓库或输出结果。
314
+ 如果 merge 出现冲突:
169
315
 
170
- ### Step 3: 写入任务进度快照(可选)
316
+ 1. 立即停止,展示冲突文件列表。
317
+ 2. 询问用户:手动解决 / 中止 merge。
318
+ 3. 绝对不能 `git merge --abort` 后静默跳过。
171
319
 
172
- 仅当 Step 0.5 识别到活动任务时执行;否则跳过本步直接进入 Step 4。
320
+ 如果用户选择 `reconfigure` 并确认回写目标分支,将 `.trellis/config.yaml` 对应 package 的 `merge_target` 更新为确认的目标;该配置变更属于父仓 dirty 文件,必须在 Step 5 的父仓检查里显式处理。
173
321
 
174
- **目的**:让下次新会话进来时能感知"任务做到哪一步了"。配套机制由 `.trellis/workflow.md` 的 `[workflow-state:no_task]` 块里的 `push-progress-recovery` guard 触发(见 3.4)。
322
+ ---
175
323
 
176
- **架构说明**:`.trellis/tasks/<task>/task.json` 在**父仓**(含 `.trellis/` 的项目根目录)的 git 跟踪范围内,与子仓(frontend / backend)独立。因此本 Step 完成后必须**额外 commit + push 父仓**(见 3.3),才能让 snapshot 真正落到 remote,跨机器恢复有效,且不留脏工作区。
324
+ ## Step 5: 写入任务进度快照与父仓 bookkeeping
177
325
 
178
- #### 3.1 AI 推断进度
326
+ 仅当统一执行计划中确认了 snapshot 时执行;否则跳过。
179
327
 
180
- 收集以下信号:
328
+ ### 5.1 补齐运行后字段
181
329
 
182
- - Step 0.5 读到的 `implement.md` 步骤清单(如缺失则只能靠 commit history 粗略推断)
183
- - 各子仓 `git log <base_branch>..HEAD --oneline`(任务分支自分叉以来的所有 commit,含本次刚 push 的)
184
- - 上次 `last_push_snapshot`(如有)— 作为基线,重点判断"上次之后又做了什么"
330
+ 业务 commit / push 完成后,按实际结果补齐:
185
331
 
186
- 基于以上信号,AI **主动给出一个 draft**(不要让用户从零列步骤),例如:
332
+ - `snapshot_at`:当前 ISO 8601 时间戳
333
+ - `branch`:实际分支;多仓不同分支时使用字典
334
+ - `pushed_commits`:各 package 的短 hash
335
+ - `notes`:保留已确认 notes;commit-only 模式追加“本地已提交,未推送”
187
336
 
188
- ```markdown
189
- 任务进度推断(请确认):
337
+ 写入方式:
190
338
 
191
- - ✅ Step 1-3 已完成(frontend abc1234 / backend def5678 覆盖了对应改动)
192
- - 🟡 Step 4 部分完成 — 看到 README.md 改了 2 处,implement.md 写要改 4 处
193
- - Step 5 未跑
339
+ 1. `<task_dir>/task.json`
340
+ 2. 解析 JSON
341
+ 3. 只设置 / 更新 `last_push_snapshot` 字段
342
+ 4. 保留其它字段原样
343
+ 5. 写回并保持原有缩进(通常 2 空格)
194
344
 
195
- 本次 push 后停在 **Step 4(部分)**,下一步 **Step 5(校验)**。
345
+ 不要覆盖整个 `task.json`。
196
346
 
197
- 确认(yes)/ 调整(说明具体改动)/ 跳过快照(skip)
198
- ```
347
+ ### 5.2 父仓 status 检查
199
348
 
200
- #### 3.2 写入 task.json
349
+ 写完 snapshot 后,在父仓根目录执行:
201
350
 
202
- 用户确认(yes 或调整后的版本)→ 在 `<task_dir>/task.json` 写入 / 更新 `last_push_snapshot` 字段:
203
-
204
- ```json
205
- "last_push_snapshot": {
206
- "snapshot_at": "<ISO 8601 时间戳>",
207
- "branch": "<任务分支名>",
208
- "pushed_commits": {
209
- "frontend": "abc1234",
210
- "backend": "def5678"
211
- },
212
- "completed_steps": ["Step 1", "Step 2", "Step 3"],
213
- "partial_step": "Step 4 (README 改了 2/4 处)",
214
- "next_step": "Step 5 (校验)",
215
- "notes": "<可选:用户补充说明>"
216
- }
351
+ ```bash
352
+ git status --short
217
353
  ```
218
354
 
219
- 字段语义:
220
- - `snapshot_at`:写快照的时间戳(必填)
221
- - `branch`:任务分支名(必填,多仓不同分支时改成字典 `{"frontend": "...", "backend": "..."}`)
222
- - `pushed_commits`:本次刚 push 的最新 commit 短 hash,按 package 名分键(必填)
223
- - `completed_steps`:implement.md 中已完成的 step 名数组(必填)
224
- - `partial_step` / `next_step` / `notes`:可选
355
+ 只允许自动处理统一计划中确认过的文件:
225
356
 
226
- 写入方式:读 `task.json` → 解析 JSON → 设置 `last_push_snapshot` 字段 → 保留其它字段原样 → 写回(保持原有 indent,通常 2 空格)。**不要**覆盖整个 task.json,只更新一个字段。
357
+ - `<task_dir>/task.json`
358
+ - 如果 Step 4 选择了 reconfigure:`.trellis/config.yaml`
227
359
 
228
- > 用户回复 `skip` 时不写入 task.json,**整个 Step 3 终止**(包括跳过 3.3 父仓提交),直接进 Step 4。
360
+ 如果父仓 status 显示其它改动,立即停止并询问用户如何处理。不要静默打包。
229
361
 
230
- #### 3.3 父仓 commit + push(同步到 remote)
362
+ 如果父仓也是本次业务仓库,snapshot / config bookkeeping 仍然使用单独 commit,不和业务 commit 混合。
231
363
 
232
- 写完 task.json 后,**必须**把这个改动 commit + push 到父仓 remote,否则:
233
- - 工作区残留脏 task.json
234
- - 跨机器 / 重新 clone 时拿不到 snapshot
235
- - 父仓 git log 缺失任务进度的演进记录
364
+ ### 5.3 提交并推送父仓 bookkeeping
236
365
 
237
366
  ```bash
238
- # 切到父仓根目录(含 .trellis/ 的目录,不是 package 子目录)
239
- cd <project_root>
240
-
241
- # 先看父仓 status,确认变更只有 task.json
242
- git status --short
243
- ```
244
-
245
- **[!] 如果父仓 status 显示 task.json 之外还有其他改动**:停下来询问用户:是否一并提交 / 拆分 / 暂存?不要静默打包。
246
-
247
- ```bash
248
- # 仅 stage 这一个文件,避免误带父仓其他改动
249
- git add .trellis/tasks/<task_dir>/task.json
250
-
251
- # commit(message 参考项目现有风格,如 chore(task): / [UPDATE] 等)
367
+ git add <task_json_path> [".trellis/config.yaml"]
252
368
  git commit -m "chore(task): update <task_name> push snapshot"
253
369
  ```
254
370
 
@@ -258,64 +374,58 @@ git commit -m "chore(task): update <task_name> push snapshot"
258
374
  git remote -v | grep -E "^origin\s+"
259
375
  ```
260
376
 
261
- - **有 remote**:`git push origin <current_branch>`(首次用 `git push -u origin <current_branch>`)
262
- - **无 remote**:仅本地 commit,跳过 push 步骤,提示用户"父仓未配 remote,snapshot 仅本地保存"
263
-
264
- #### 3.4 新会话恢复(被动机制,无需在本步操作)
377
+ - remote:`git push origin <current_branch>`;首次使用 `git push -u origin <current_branch>`。
378
+ - remote:仅本地 commit,提示用户“父仓未配 remote,snapshot 仅本地保存”。
265
379
 
266
- 写入并 push 后,下次新会话进来时:
380
+ ---
267
381
 
268
- 1. SessionStart 检测到无 active task pointer → 输出 `<task-status>Status: NO ACTIVE TASK</task-status>`
269
- 2. UserPromptSubmit 每轮注入 `[workflow-state:no_task]` 块,含 skill-garden 的 `push-progress-recovery` guard
270
- 3. AI 看到 guard → 扫描 `.trellis/tasks/*/task.json` 找 `status=in_progress` 的任务 → 读 `last_push_snapshot` → 主动告诉用户「发现未完成任务 X,上次 push 完成到 Step Y,下一步 Z」并建议 `task.py start <task>` 恢复
382
+ ## Step 6: 输出结果
271
383
 
272
- ### Step 4: 输出结果
384
+ 使用结果表汇总:
273
385
 
274
386
  ```markdown
275
387
  ## Push 结果
276
388
 
277
389
  | 仓库 | 分支 | 目标 | commit | 状态 |
278
390
  |------|------|------|--------|------|
279
- | frontend | v1.3 | test | abc1234 feat(...): ... | 已合并 |
280
- | backend | v1.3 | test | def5678 fix(...): ... | ⏭️ 跳过合并 |
281
-
282
- 所有变更已推送到目标分支。
283
- ```
391
+ | frontend | v1.3 | test | abc1234 feat(...): ... | 已合并 |
392
+ | backend | v1.3 | - | def5678 fix(...): ... | 已推送,跳过合并 |
284
393
 
285
- Step 3 写入了 `last_push_snapshot`,在结果末尾追加一行:
286
-
287
- ```markdown
288
- 任务进度快照已写入 `<task_dir>/task.json`:完成 Step 1-3,下一步 Step 5。
394
+ 任务进度快照:已写入 `<task_dir>/task.json`,完成 Step 1-3,下一步 Step 5。
395
+ 父仓同步:已提交并推送 `chore(task): update <task_name> push snapshot`。
289
396
  ```
290
397
 
291
- ---
292
-
293
- ## 语义参数(通过自然语 / skill args 传入)
398
+ 如果部分仓库已成功、后续失败,必须明确列出:
294
399
 
295
- | 语义 | 说明 | 用户怎么说 |
296
- |------|------|-----------|
297
- | 默认 | 自动检测所有有变更的仓库并处理 | `/trellis-push` |
298
- | commit-only | 只 commit 不 push(Phase 3.4「commit now, push later」),跳过 2.4/2.5 | 「只提交不推」/「commit-only」 |
299
- | 指定仓库 | 只处理指定仓库 | 「只 push 前端」/「push frontend」 |
300
- | 重新配置 | 重新询问目标分支 | 「重新配置 push 目标分支」/「reconfigure push」 |
301
- | 临时目标 | 临时指定目标分支(不修改配置) | 「push 到 hotfix 分支」 |
400
+ - 已完成的 commit / push / merge
401
+ - 失败位置
402
+ - 当前所在分支
403
+ - 用户下一步需要处理什么
302
404
 
303
405
  ---
304
406
 
305
407
  ## 安全机制
306
408
 
307
- 1. **暂存确认**每个仓库暂存前展示文件列表,用户确认
308
- 2. **commit message 确认**展示生成的 message,用户可修改
309
- 3. **merge 冲突处理** 冲突时暂停,不静默跳过
310
- 4. **不碰主分支**如果目标分支是 `master` / `main`,额外警告确认
311
- 5. **不使用 force push**始终使用普通 push
409
+ 1. **统一执行计划确认**文件列表、commit message、push/merge 意图、snapshot 草案一起确认。
410
+ 2. **未识别 dirty 文件隔离**默认不纳入提交,除非用户明确确认。
411
+ 3. **执行前复核**git 状态与计划不一致时停止,不临时扩展范围。
412
+ 4. **snapshot 合并确认** 语义字段执行前确认,运行后字段执行后补齐。
413
+ 5. **父仓 bookkeeping 隔离**只提交已确认的 `task.json` / `config.yaml`,其它 dirty 文件必须询问。
414
+ 6. **merge 冲突处理** — 冲突时暂停,不静默跳过。
415
+ 7. **主分支保护** — 目标分支是 `master` / `main` 时必须在计划中额外警告确认。
416
+ 8. **不使用 force push** — 始终使用普通 push。
312
417
 
313
418
  ---
314
419
 
315
420
  ## 反模式(避免)
316
421
 
317
- - ❌ `git add -A`(可能误提交敏感文件)
318
- - ❌ merge 冲突后静默 abort(用户需要知道)
319
- - ❌ 未经确认直接 commit(必须让用户看到 message)
320
- - ❌ force push 到目标分支
422
+ - ❌ 在展示统一执行计划前执行 `git add` / commit / push / merge
423
+ - ❌ `git add -A` 或 `git add .`
424
+ - ❌ 把未识别 dirty 文件静默纳入提交
425
+ - ❌ commit message 未展示给用户就提交
426
+ - ❌ push 后临时追问 merge,而不是在计划中提前确认
427
+ - ❌ snapshot 语义内容未确认就写入 task.json
428
+ - ❌ 父仓 snapshot commit 混入业务代码提交
429
+ - ❌ merge 冲突后静默 abort 或跳过
430
+ - ❌ force push 到当前分支或目标分支
321
431
  - ❌ 在目标分支上直接开发(只 merge,不在目标分支上改代码)