flower-trellis 0.3.1-beta.7 → 0.4.0-beta.0
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/README.md +1 -1
- package/enhancements/0.6/.agents/skills/trellis-auto-loop/SKILL.md +131 -0
- package/enhancements/0.6/.agents/skills/trellis-push/SKILL.md +16 -1
- package/enhancements/0.6/.agents/skills/trellis-route/SKILL.md +21 -16
- package/enhancements/0.6/.agents/skills/trellis-route/scripts/route_state.py +92 -3
- package/enhancements/0.6/.claude/skills/trellis-auto-loop/SKILL.md +131 -0
- package/enhancements/0.6/.claude/skills/trellis-push/SKILL.md +16 -1
- package/enhancements/0.6/.claude/skills/trellis-route/SKILL.md +21 -16
- package/enhancements/0.6/.claude/skills/trellis-route/scripts/route_state.py +92 -3
- package/enhancements/0.6/overrides/workflow-states/planning-inline.md +1 -0
- package/enhancements/0.6/overrides/workflow-states/planning.md +1 -0
- package/enhancements/0.6/overrides/workflow.md +9 -1
- package/enhancements/0.6/scripts/auto_loop.py +782 -0
- package/enhancements/MANIFEST.json +11 -4
- package/package.json +2 -2
- package/src/cli.js +2 -1
- package/src/constants.js +3 -0
- package/src/lib/apply-enhancements.js +11 -2
- package/src/lib/copy-scripts.js +36 -0
- package/src/lib/pick-platforms.js +4 -1
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ flower-trellis -v
|
|
|
82
82
|
| `--target <dir>` | 目标目录(默认当前目录) |
|
|
83
83
|
| `--no-update-check` | 本次跳过 flower-trellis 新版本检测(等价环境变量 `FLOWER_NO_UPDATE_CHECK=1`) |
|
|
84
84
|
|
|
85
|
-
未指定平台时,交互模式会弹出多选菜单(默认勾选 Claude Code + Codex);也可直接传 `--claude` / `--codex` / `--cursor` 等指定,或用 `-y`
|
|
85
|
+
未指定平台时,交互模式会弹出多选菜单(默认勾选 Claude Code + Codex);也可直接传 `--claude` / `--codex` / `--cursor` / `--devin` / `--zcode` / `--trae` 等指定,或用 `-y` 跳过菜单。`--windsurf` 仍作为 Devin 的旧别名透传给 Trellis。其余未识别的 flag(如 `-u`、`-f`、`--template`、`--with-statusline`)一律透传给 Trellis。
|
|
86
86
|
|
|
87
87
|
### 自动版本检测
|
|
88
88
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trellis-auto-loop
|
|
3
|
+
description: "启动、恢复和推进 Trellis 自动任务循环。用于用户明确要求 auto loop、自动跑任务、/goal 类似流程、一次跑多个任务、继续自动 run、查看/停止 auto-loop,或压缩恢复后需要从 .trellis/scripts/auto_loop.py 读取下一步。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Trellis Auto Loop
|
|
7
|
+
|
|
8
|
+
用 `.trellis/scripts/auto_loop.py` 驱动一个接近 `/goal` 的任务循环。Python runner 是状态权威;本 skill 只负责把用户意图映射到 runner 命令,并按 runner 返回的 action 调用现有 Trellis workflow / skill / subagent。
|
|
9
|
+
|
|
10
|
+
## 核心规则
|
|
11
|
+
|
|
12
|
+
- 只有用户明确要求自动跑、auto loop、goal-like、继续自动 run、批量任务队列时才启动或恢复;不要把普通实现请求自动升级为 auto-loop。
|
|
13
|
+
- 每次开始、恢复、压缩后继续时,先运行 runner 的 `resume` 或 `next`,不要凭聊天摘要推断下一步。
|
|
14
|
+
- 每完成一个 action,必须用 `record --action <next 返回的 action>` 精确写回结果;runner 会拒绝缺失或不匹配的 action。写回后立即再调用 `next`,直到 `done`、`blocked` 或需要用户决策。
|
|
15
|
+
- 默认 profile 是 `commit-only`:自动推进到本地 commit,不 push、不发布、不归档。
|
|
16
|
+
- 多任务只按用户显式给出的任务顺序执行;同一 worktree 不并发。
|
|
17
|
+
- route 临时授权写在 auto-loop runtime 中,低于个人 `.trellis/.route-prefs.tmp`;不要写个人偏好。
|
|
18
|
+
- planning start gate 会按有效 route 判断 JSONL 是否必需:inline / check-all-inline 可不因 seed-only JSONL 停住;个人默认 subagent 仍优先于 auto inline 授权并要求 curated context。
|
|
19
|
+
- 代码提交必须走 `trellis-push` 的 commit-only 语义;不要裸 `git commit` / `git push`。
|
|
20
|
+
|
|
21
|
+
## 启动
|
|
22
|
+
|
|
23
|
+
用户给了任务列表时,按原顺序传入;用户只说当前任务时,用 `task.py current --source` 的当前任务。
|
|
24
|
+
|
|
25
|
+
子代理可用的 workflow 默认写入临时 route 授权:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python3 ./.trellis/scripts/auto_loop.py start \
|
|
29
|
+
--tasks <task> [<task> ...] \
|
|
30
|
+
--profile commit-only \
|
|
31
|
+
--route-implement subagent \
|
|
32
|
+
--route-check check-all-subagent
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
inline-only 场景改用:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python3 ./.trellis/scripts/auto_loop.py start \
|
|
39
|
+
--tasks <task> [<task> ...] \
|
|
40
|
+
--profile commit-only \
|
|
41
|
+
--route-implement inline \
|
|
42
|
+
--route-check check-all-inline
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
如果用户个人 `.trellis/.route-prefs.tmp` 存在,`trellis-route` 会优先使用个人偏好;auto 授权只负责 prefs miss 时减少询问。
|
|
46
|
+
|
|
47
|
+
启动后立即运行:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python3 ./.trellis/scripts/auto_loop.py next
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 恢复
|
|
54
|
+
|
|
55
|
+
压缩、重开会话、用户说“继续自动跑 / continue auto loop”时:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python3 ./.trellis/scripts/auto_loop.py resume
|
|
59
|
+
python3 ./.trellis/scripts/auto_loop.py next
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`resume_capsule` 只用于展示;下一步以 `next` 返回的 JSON 为准。
|
|
63
|
+
|
|
64
|
+
## Action 映射
|
|
65
|
+
|
|
66
|
+
| runner action | 主 agent 动作 | 成功 record |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| `refresh_brief` | 使用 `trellis-task-brief` 生成并展示 brief | `record --action refresh_brief --result ok` |
|
|
69
|
+
| `start_task` | 执行返回的 `task.py start ...` 命令 | `record --action start_task --result ok` |
|
|
70
|
+
| `run_implement` | 进入 Phase 2.1,先用 `trellis-route(target=implement)` 决定 inline/subagent,再实现 | `record --action run_implement --result ok` |
|
|
71
|
+
| `run_check_all` | 进入 Phase 2.2,先用 `trellis-route(target=check)`,执行 check-all | `record --action run_check_all --result ok` |
|
|
72
|
+
| `run_fix` | 根据 `last_failure` 修复,复用当前任务 implement route | `record --action run_fix --result ok` |
|
|
73
|
+
| `run_recheck` | 复用当前任务 check route,重新 check-all | `record --action run_recheck --result ok` |
|
|
74
|
+
| `run_spec_update` | 有代码/测试证据时用 `trellis-update-spec`;无必要更新也 record ok | `record --action run_spec_update --result ok` |
|
|
75
|
+
| `commit_only` | 使用 `trellis-push` commit-only auto-loop 预授权路径,只提交当前任务可归属文件 | `record --action commit_only --result ok --commit <hash>` |
|
|
76
|
+
|
|
77
|
+
失败时写回:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python3 ./.trellis/scripts/auto_loop.py record \
|
|
81
|
+
--action <action> \
|
|
82
|
+
--result failed \
|
|
83
|
+
--failure-type <type> \
|
|
84
|
+
--summary "<失败摘要>" \
|
|
85
|
+
--files <file> [<file> ...]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
需要用户产品决策或越权时写回 blocked:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python3 ./.trellis/scripts/auto_loop.py record \
|
|
92
|
+
--action <action> \
|
|
93
|
+
--result blocked \
|
|
94
|
+
--failure-type <type> \
|
|
95
|
+
--summary "<阻塞原因>"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
runner 会按 3 轮 fix/recheck 预算决定继续、跳过当前任务或结束队列。
|
|
99
|
+
|
|
100
|
+
## Commit-Only 预授权
|
|
101
|
+
|
|
102
|
+
auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本地提交”的一次性预授权。只有同时满足这些条件时,`trellis-push` 可以跳过二次聊天确认:
|
|
103
|
+
|
|
104
|
+
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,且 `outstanding_action.action=commit_only`、`outstanding_action.task` 等于当前活动任务。
|
|
105
|
+
- profile 是 `commit-only`。
|
|
106
|
+
- 模式是 commit-only,不 push、不 merge、不发布、不归档。
|
|
107
|
+
- 提交计划只包含当前任务可归属文件;未识别 dirty 文件保留未提交并写入结果摘要。
|
|
108
|
+
- 执行前复核 git 状态仍与计划一致。
|
|
109
|
+
|
|
110
|
+
如果计划包含未识别 staged 文件、冲突、push/merge/release/archive、真实外部系统或生产数据效果,停止并把当前任务记为 blocked。
|
|
111
|
+
|
|
112
|
+
## 状态与停止
|
|
113
|
+
|
|
114
|
+
查看:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
python3 ./.trellis/scripts/auto_loop.py status
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
停止:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python3 ./.trellis/scripts/auto_loop.py stop --reason "<原因>"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 不要做
|
|
127
|
+
|
|
128
|
+
- 不要手写或手改 `.trellis/.runtime/auto-loop/*.json`。
|
|
129
|
+
- 不要把 `.trellis/.runtime/` 或 `.trellis/.route-prefs.tmp` 加入提交。
|
|
130
|
+
- 不要在 auto-loop 外把普通 check 的 post-check stop gate 当成可跳过。
|
|
131
|
+
- 不要为模糊需求自动创建任务并开跑;先回到 Trellis planning。
|
|
@@ -8,6 +8,8 @@ description: "提交并推送配置仓库,可选合并到目标分支,并同
|
|
|
8
8
|
|
|
9
9
|
核心原则:**先计划、一次确认、后执行**。在任何 `git add`、`git commit`、`git push`、`git merge` 之前,必须先展示完整执行计划,并获得用户确认。
|
|
10
10
|
|
|
11
|
+
例外:当 `trellis-auto-loop` 已显式以 `profile=commit-only` 启动,且 runner 当前有 `outstanding_action.action=commit_only` 时,用户启动 auto-loop 本身就是本次 run 内任务相关本地提交的预授权。此时仍必须生成并自检完整计划,但如果计划只包含当前任务可归属文件、模式为 commit-only、不会 push/merge/release/archive,并且执行后会把 commit hash 回写 runner,可以跳过二次聊天确认直接执行。
|
|
12
|
+
|
|
11
13
|
支持多仓库(frontend / backend 等),merge 目标分支记录在 `.trellis/config.yaml` 的 `packages.<name>.merge_target` 中。
|
|
12
14
|
|
|
13
15
|
---
|
|
@@ -62,9 +64,22 @@ Step 6 输出结果
|
|
|
62
64
|
| 重新配置 | 本次允许重新指定 merge 目标,并回写 `merge_target` | `重新配置 push 目标分支` / `reconfigure push` |
|
|
63
65
|
| 临时目标 | 本次临时指定 merge 目标,不修改配置 | `push 到 hotfix 分支` |
|
|
64
66
|
| snapshot-only | 不提交业务代码,只写入 / 同步任务进度快照 | `只更新 snapshot` / `snapshot-only` |
|
|
67
|
+
| auto-loop commit-only | 由 `trellis-auto-loop` runner 的 `commit_only` action 触发,只提交本任务可归属文件,不二次确认、不 push | `trellis-auto-loop` 内部触发 |
|
|
65
68
|
|
|
66
69
|
`snapshot-only` 只在用户明确要求时使用。它仍必须展示统一执行计划;`pushed_commits` 取计划中确认的现有 commit,或按用户说明记录。
|
|
67
70
|
|
|
71
|
+
### 0.1.1 auto-loop commit-only 判定
|
|
72
|
+
|
|
73
|
+
只有同时满足以下条件,才可走 auto-loop 预授权路径:
|
|
74
|
+
|
|
75
|
+
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,profile 为 `commit-only`。
|
|
76
|
+
- status 摘要里的 `outstanding_action.action` 是 `commit_only`,且 `outstanding_action.task` 等于当前活动任务。
|
|
77
|
+
- 本次 `trellis-push` 语义是 commit-only,不包含 push / merge / release / archive。
|
|
78
|
+
- 计划拟提交文件全部能归属当前任务;未识别 dirty 文件不纳入提交。
|
|
79
|
+
- 执行前复核 git 状态与计划一致。
|
|
80
|
+
|
|
81
|
+
任一条件不满足时,不得使用预授权。普通 `trellis-push` 继续走“展示计划并等待确认”的规则。
|
|
82
|
+
|
|
68
83
|
### 0.2 发现候选 Git 仓库
|
|
69
84
|
|
|
70
85
|
读取 `.trellis/config.yaml` 中的 `packages` 配置,但不要把 `git: true` 当作唯一仓库发现规则。`git: true` 主要用于 Trellis session context 展示独立包仓库状态;`trellis-push` 必须以实际 Git root 为准发现可提交仓库:
|
|
@@ -131,7 +146,7 @@ git log <base_branch>..HEAD --oneline
|
|
|
131
146
|
|
|
132
147
|
## Step 2: 生成统一执行计划
|
|
133
148
|
|
|
134
|
-
这是唯一的常规确认点。**确认前禁止执行任何 `git add` / commit / push / merge / task.json 写入。**
|
|
149
|
+
这是唯一的常规确认点。**确认前禁止执行任何 `git add` / commit / push / merge / task.json 写入。** 唯一例外是已满足 Step 0.1.1 的 auto-loop commit-only 预授权;该路径仍要生成计划并执行自检,只是不再等待用户二次确认。
|
|
135
150
|
|
|
136
151
|
### 2.1 生成业务提交计划
|
|
137
152
|
|
|
@@ -13,9 +13,9 @@ description: |
|
|
|
13
13
|
|
|
14
14
|
# Trellis 路由器:implement / check 执行模式选择
|
|
15
15
|
|
|
16
|
-
主 agent 进入 Phase 2.1 实现路由或 Phase 2.2 检查路由时调用本 skill。当前上下文或 session runtime state
|
|
16
|
+
主 agent 进入 Phase 2.1 实现路由或 Phase 2.2 检查路由时调用本 skill。当前上下文或 session runtime state 内已有合法来源、target 匹配、且 task 等于当前任务路径的最近 route 决策时,后续实现、修复、重检默认复用该决策;没有合法决策时才进入本 skill 或同编号 fallback。提交前确实需要最终复查时,回到 Phase 2.2 并复用当前任务的合法 check route,除非用户明确要求重选。
|
|
17
17
|
|
|
18
|
-
个人配置只写入 `.trellis/.route-prefs.tmp`。该文件匹配 `.trellis/.gitignore` 的 `*.tmp` 规则,属于开发者本地偏好,不纳入 git,也不影响其他开发者。
|
|
18
|
+
个人配置只写入 `.trellis/.route-prefs.tmp`。该文件匹配 `.trellis/.gitignore` 的 `*.tmp` 规则,属于开发者本地偏好,不纳入 git,也不影响其他开发者。auto-loop 可在 `.trellis/.runtime/auto-loop/<run-id>.json` 写入临时 route 授权;它不是个人偏好,优先级低于 `.route-prefs.tmp`,只用于减少 auto 模式下的交互打断。
|
|
19
19
|
|
|
20
20
|
本轮 route 决策写入当前 session runtime 文件 `.trellis/.runtime/sessions/<context-key>.json` 的 `route_decisions` 字段。该文件匹配 `.trellis/.gitignore` 的 `.runtime/` 规则,只保存当前 AI session/window 的执行状态,用于压缩后恢复;它不是任务属性,不写入 `.trellis/tasks/**`,也不是长期团队配置。
|
|
21
21
|
|
|
@@ -25,9 +25,9 @@ description: |
|
|
|
25
25
|
|
|
26
26
|
个人 route 配置只决定“已获准执行后的模式”,不是开工授权。调用 helper 前,必须确认当前 workflow 已允许进入对应 target:implement 需要任务已完成规划确认并处于 `in_progress`;check 用于 Phase 2.2 检查执行,或用户明确要求最终复查 / 轻量检查。最终复查只有在 Phase 2.2 结果缺失、风险较高或用户明确要求复查时才回到 Phase 2.2;回到 Phase 2.2 后优先复用当前任务的合法 check route,除非用户明确要求重选/临时改/清除默认。如果仍在 planning、等待用户确认,或用户表达“等一下 / 我再想想”,停止,不读取 runtime/prefs。
|
|
27
27
|
|
|
28
|
-
合法 route 决策必须能追溯到 `trellis-route`、同编号 fallback
|
|
28
|
+
合法 route 决策必须能追溯到 `trellis-route`、同编号 fallback 选项、由本 skill 读取到的有效 `.trellis/.route-prefs.tmp` 配置,或由 route helper 校验过的 auto-loop 临时 route 授权,并且 `task` 字段必须等于当前 `task.py current --source` 返回的任务路径。runtime state 只能保存和恢复这些原始合法来源,不能把 `.runtime` 自身当成新的 `route_decision.source`。用户自然语言说过“inline/subagent”、compact summary、SessionStart 摘要、`codex-mode`、空 `.route-prefs.tmp`、旧单值偏好,都不能单独作为有效 route 决策。
|
|
29
29
|
|
|
30
|
-
当前上下文内已有 target
|
|
30
|
+
当前上下文内已有 target 匹配、task 等于当前任务路径、且来源合法的 route 决策时,后续实现、check 发现问题、用户指出刚检查过的实现有问题、修复后重检、提交前复查均默认复用最近 implement/check 路由;除非用户明确要求重选/临时改/清除默认,不再调用本 skill。当前上下文没有 route 决策但 runtime state 命中时,本 skill 恢复该决策并输出同样的结构化 `route_decision`。如果上下文里只有上一个任务的 `route_decision`,必须忽略并重新解析当前任务。
|
|
31
31
|
|
|
32
32
|
Codex inline mode 只表示主会话默认直接执行,不是 route 选项过滤器。即使当前上下文出现 `<codex-mode>inline...do not dispatch...</codex-mode>` 或 `workflow-state:in_progress-inline`,也不能推断“只能 inline”或跳过 subagent 选项;仍必须通过 helper resolve runtime/prefs,或在无有效配置时展示正常 inline/subagent 选项。若本 skill 的紧邻路由决定是 subagent,本步骤允许主 agent dispatch 对应 implement/check sub-agent;禁止的是绕过 `trellis-route` 直接 dispatch。
|
|
33
33
|
|
|
@@ -50,7 +50,7 @@ Codex inline mode 只表示主会话默认直接执行,不是 route 选项过
|
|
|
50
50
|
|
|
51
51
|
## Step 0.5: 解析已有 route state
|
|
52
52
|
|
|
53
|
-
仅在没有覆盖意图、当前上下文没有 target 匹配的合法 `route_decision` 时调用 helper 解析已有状态。helper 的解析顺序固定为:当前 session runtime 文件里的 `route_decisions` → `.trellis/.route-prefs.tmp
|
|
53
|
+
仅在没有覆盖意图、当前上下文没有 target + 当前 task 匹配的合法 `route_decision` 时调用 helper 解析已有状态。helper 的解析顺序固定为:当前 session runtime 文件里的 `route_decisions` → `.trellis/.route-prefs.tmp` → `.trellis/.runtime/auto-loop/<run-id>.json` 临时授权。命中 `.route-prefs.tmp` 或 auto-loop 临时授权时,helper 会自动把对应决策写回当前 session runtime,后续压缩恢复不需要再次读 prefs 或 auto-loop 状态。
|
|
54
54
|
|
|
55
55
|
调用随本 skill 分发的 helper;不要在对话中内嵌或改写 helper 逻辑:
|
|
56
56
|
|
|
@@ -60,7 +60,7 @@ python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target <im
|
|
|
60
60
|
python3 .claude/skills/trellis-route/scripts/route_state.py resolve --target <implement|check>
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
helper 只接受当前 session 或唯一 session fallback 的 `.trellis/.runtime/sessions/<context-key>.json`,并只从 `route_decisions.<target>`
|
|
63
|
+
helper 只接受当前 session 或唯一 session fallback 的 `.trellis/.runtime/sessions/<context-key>.json`,并只从 `route_decisions.<target>` 恢复当前任务的决策。命中时输出 `{"status":"hit", ...}`,其中默认输出里的 `task` / `mode` / `source` 已经过 task/target/source/mode/scope 校验,可跳过 Step 2 并进入 Step 3 输出决策。`origin=route-prefs` 表示来自个人 route 配置,并且 helper 已写回 session runtime state;`origin=auto-loop` 表示来自 auto-loop 临时授权且 helper 已写回 session runtime state;`origin=runtime` 表示来自 session runtime state。
|
|
64
64
|
|
|
65
65
|
helper 默认输出为精简 JSON,只包含 route 执行必需的 `status`、`origin`、`mode`、`source`/`reason` 等字段。需要排查完整 `decision`、session 文件、context key、任务路径、个人配置路径或写回标记时,在同一命令末尾加 `--verbose`;不要为了诊断信息额外读取 runtime 文件。
|
|
66
66
|
|
|
@@ -181,7 +181,9 @@ python3 .agents/skills/trellis-route/scripts/route_state.py clear-pref --target
|
|
|
181
181
|
python3 .claude/skills/trellis-route/scripts/route_state.py clear-pref --target <implement|check>
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
helper 写入规则:保留另一个 target 的 runtime 决策和偏好;覆盖当前 target;`source` 保持原始合法来源,正常 skill 交互用 `trellis-route`,普通聊天编号 fallback 用 `numbered-fallback`,prefs 命中由 helper 写 `route-prefs`;保留 session runtime 文件中的 `platform`、`current_task`、`current_run` 等既有字段;内部 `task` 必须写当前 `task.py current --source` 的任务路径。写入失败不阻塞本次 route 输出,但要在回复中简短说明未持久化,压缩后可能再次询问。
|
|
184
|
+
helper 写入规则:保留另一个 target 的 runtime 决策和偏好;覆盖当前 target;`source` 保持原始合法来源,正常 skill 交互用 `trellis-route`,普通聊天编号 fallback 用 `numbered-fallback`,prefs 命中由 helper 写 `route-prefs`,auto-loop 临时授权命中由 helper 写 `auto-loop`;保留 session runtime 文件中的 `platform`、`current_task`、`current_run`、`current_auto_run` 等既有字段;内部 `task` 必须写当前 `task.py current --source` 的任务路径。写入失败不阻塞本次 route 输出,但要在回复中简短说明未持久化,压缩后可能再次询问。
|
|
185
|
+
|
|
186
|
+
当同一 session 从一个任务切换到另一个任务时,helper 写入当前任务任一 target 的决策前会清理 runtime 中属于其他任务的 `route_decisions`。个人默认仍保留在 `.trellis/.route-prefs.tmp`;清理只影响当前 session 的临时恢复状态,目的是避免新任务的 check 阶段误复用上一个任务的 check 路由。
|
|
185
187
|
|
|
186
188
|
---
|
|
187
189
|
|
|
@@ -205,6 +207,7 @@ helper 写入规则:保留另一个 target 的 runtime 决策和偏好;覆
|
|
|
205
207
|
```markdown
|
|
206
208
|
路由决定:<inline/subagent> <implement | check-all | check>
|
|
207
209
|
[来自个人 route 配置:`.trellis/.route-prefs.tmp` (<key>=<value>)。]
|
|
210
|
+
[来自 auto-loop 临时 route 授权:`.trellis/.runtime/auto-loop/<run-id>.json`。]
|
|
208
211
|
[来自 session runtime route state:`.trellis/.runtime/sessions/<context-key>.json` 的 `route_decisions`。]
|
|
209
212
|
[已写入 session runtime route state:`.trellis/.runtime/sessions/<context-key>.json` 的 `route_decisions`。]
|
|
210
213
|
[说明:用户明确请求轻量检查,使用隐藏逃生口。]
|
|
@@ -212,8 +215,9 @@ helper 写入规则:保留另一个 target 的 runtime 决策和偏好;覆
|
|
|
212
215
|
route_decision:
|
|
213
216
|
target: <implement | check>
|
|
214
217
|
mode: <inline | subagent | check-all-inline | check-all-subagent | check-inline | check-subagent>
|
|
215
|
-
source: <trellis-route | route-prefs | numbered-fallback>
|
|
218
|
+
source: <trellis-route | route-prefs | auto-loop | numbered-fallback>
|
|
216
219
|
scope: task
|
|
220
|
+
task: <current task path>
|
|
217
221
|
|
|
218
222
|
接下来主 agent 应当:
|
|
219
223
|
- <路由表里对应的工具调用形式>
|
|
@@ -223,7 +227,7 @@ route_decision:
|
|
|
223
227
|
- <要避免的工具调用>
|
|
224
228
|
```
|
|
225
229
|
|
|
226
|
-
中括号内行为条件性出现:仅命中个人配置时显示配置行;仅命中 runtime state 时显示“来自”行;写入 runtime state 成功时显示“已写入”行;仅轻量 check 时显示隐藏逃生口说明;仅 implement subagent + skip_compile=true 时附加“跳过编译”段。`route_decision`
|
|
230
|
+
中括号内行为条件性出现:仅命中个人配置时显示配置行;仅命中 runtime state 时显示“来自”行;写入 runtime state 成功时显示“已写入”行;仅轻量 check 时显示隐藏逃生口说明;仅 implement subagent + skip_compile=true 时附加“跳过编译”段。`route_decision` 必须保留在回复中,并至少保留 target/mode/source/scope/task;需要 path/decided_at 等诊断字段时重新调用 helper 并加 `--verbose`。compact summary 若只有自然语言描述,后续 agent 仍应优先读取 runtime state,而不是把 summary 当证据。
|
|
227
231
|
|
|
228
232
|
---
|
|
229
233
|
|
|
@@ -233,13 +237,14 @@ route_decision:
|
|
|
233
237
|
2. **runtime state 私有**:`.trellis/.runtime/sessions/` 是 session/window 状态,gitignored,不能进入提交计划。
|
|
234
238
|
3. **压缩恢复少打断**:当前上下文没有 route 决策时,先读 runtime state;命中当前任务/target 的合法决策就复用,不查 `trellis mem`,也不重问。
|
|
235
239
|
4. **个人默认次于本轮决策**:runtime state 表示“本轮已选”,优先于 `.route-prefs.tmp`。
|
|
236
|
-
5.
|
|
237
|
-
6.
|
|
238
|
-
7.
|
|
239
|
-
8.
|
|
240
|
-
9.
|
|
241
|
-
10.
|
|
242
|
-
11.
|
|
240
|
+
5. **auto 授权低于个人默认**:auto-loop 临时授权只在 runtime 和个人偏好都 miss 时生效。
|
|
241
|
+
6. **显式覆盖优先于一切**:用户要求临时改、重新选择或清除默认时,必须重新展示选项,不能让 runtime state 或配置优先。
|
|
242
|
+
7. **当前任务复用路由**:当前任务内已有合法来源的最近 implement/check 路由时,后续实现、修复、重检和复查默认沿用,不再次询问模式。
|
|
243
|
+
8. **check 默认全面检查**:普通 check 路由只展示 `check-all` inline/subagent,不推荐轻量 `trellis-check`。
|
|
244
|
+
9. **轻量 check 是隐藏逃生口**:只有用户明确请求 `light check` / `轻量检查` 时才可走轻量 `trellis-check`。
|
|
245
|
+
10. **决策与执行分离**:本 skill 只输出指令,下一轮由主 agent 调工具。
|
|
246
|
+
11. **严格执行用户选择**:路由结论一旦输出,主 agent 必须按指令执行,不可“出于谨慎”再换路径。
|
|
247
|
+
12. **Codex inline 不裁剪选项**:Codex inline 是默认执行模式,不是只能 inline 的强制模式;route 明确选中 subagent 时,本步骤可按 subagent 路径执行。
|
|
243
248
|
|
|
244
249
|
---
|
|
245
250
|
|
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
from typing import Any
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
VALID_SOURCES = {"trellis-route", "numbered-fallback", "route-prefs"}
|
|
15
|
+
VALID_SOURCES = {"trellis-route", "numbered-fallback", "route-prefs", "auto-loop"}
|
|
16
16
|
VALID_MODES = {
|
|
17
17
|
"implement": {"inline", "subagent"},
|
|
18
18
|
"check": {
|
|
@@ -83,6 +83,7 @@ def _output(args: argparse.Namespace, data: dict[str, Any], verbose: dict[str, A
|
|
|
83
83
|
def _decision_summary(decision: dict[str, Any]) -> dict[str, Any]:
|
|
84
84
|
"""提取默认输出需要的最小 route 决策字段。"""
|
|
85
85
|
return {
|
|
86
|
+
"task": decision.get("task"),
|
|
86
87
|
"mode": decision.get("mode"),
|
|
87
88
|
"source": decision.get("source"),
|
|
88
89
|
}
|
|
@@ -129,6 +130,16 @@ def _pref_path(repo_root: Path) -> Path:
|
|
|
129
130
|
return repo_root / ".trellis/.route-prefs.tmp"
|
|
130
131
|
|
|
131
132
|
|
|
133
|
+
def _auto_loop_dir(repo_root: Path) -> Path:
|
|
134
|
+
"""返回 auto-loop runtime 目录。"""
|
|
135
|
+
return repo_root / ".trellis/.runtime/auto-loop"
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _auto_loop_pointer(repo_root: Path) -> Path:
|
|
139
|
+
"""返回当前 auto-loop run 指针文件。"""
|
|
140
|
+
return _auto_loop_dir(repo_root) / "current.json"
|
|
141
|
+
|
|
142
|
+
|
|
132
143
|
def _read_prefs(repo_root: Path) -> dict[str, str]:
|
|
133
144
|
"""读取个人 route 默认配置,只保留合法 key-value。"""
|
|
134
145
|
path = _pref_path(repo_root)
|
|
@@ -149,6 +160,47 @@ def _read_prefs(repo_root: Path) -> dict[str, str]:
|
|
|
149
160
|
return prefs
|
|
150
161
|
|
|
151
162
|
|
|
163
|
+
def _auto_route_mode(repo_root: Path, context_key: str, target: str) -> tuple[str | None, Path | None, str | None]:
|
|
164
|
+
"""读取当前 auto-loop run 的临时 route 授权。
|
|
165
|
+
|
|
166
|
+
auto 授权低于个人 `.route-prefs.tmp`,只在当前 session runtime 绑定了
|
|
167
|
+
`current_auto_run`,或全局 current 指针能指向唯一 running run 时生效。命中后
|
|
168
|
+
`resolve` 会写回 session runtime,后续压缩恢复仍走普通 route 决策路径。
|
|
169
|
+
"""
|
|
170
|
+
session_path = _session_path(repo_root, context_key)
|
|
171
|
+
session = _read_json(session_path)
|
|
172
|
+
run_id = session.get("current_auto_run")
|
|
173
|
+
|
|
174
|
+
if not isinstance(run_id, str) or not run_id.strip():
|
|
175
|
+
pointer = _read_json(_auto_loop_pointer(repo_root))
|
|
176
|
+
run_id = pointer.get("run_id")
|
|
177
|
+
|
|
178
|
+
candidate_paths: list[Path] = []
|
|
179
|
+
if isinstance(run_id, str) and run_id.strip():
|
|
180
|
+
candidate_paths.append(_auto_loop_dir(repo_root) / f"{run_id.strip()}.json")
|
|
181
|
+
else:
|
|
182
|
+
for path in sorted(_auto_loop_dir(repo_root).glob("auto-*.json")):
|
|
183
|
+
state = _read_json(path)
|
|
184
|
+
if state.get("status") == "running":
|
|
185
|
+
candidate_paths.append(path)
|
|
186
|
+
if len(candidate_paths) != 1:
|
|
187
|
+
return None, None, "no-unique-auto-run"
|
|
188
|
+
|
|
189
|
+
path = candidate_paths[0]
|
|
190
|
+
state = _read_json(path)
|
|
191
|
+
if state.get("status") != "running":
|
|
192
|
+
return None, path, "auto-run-not-running"
|
|
193
|
+
|
|
194
|
+
auth = state.get("route_authorization")
|
|
195
|
+
if not isinstance(auth, dict):
|
|
196
|
+
return None, path, "no-route-authorization"
|
|
197
|
+
|
|
198
|
+
mode = auth.get(target)
|
|
199
|
+
if mode in PREF_MODES[target]:
|
|
200
|
+
return mode, path, None
|
|
201
|
+
return None, path, "invalid-auto-route-mode"
|
|
202
|
+
|
|
203
|
+
|
|
152
204
|
def _write_prefs(repo_root: Path, prefs: dict[str, str]) -> None:
|
|
153
205
|
"""写入个人 route 默认配置;为空则删除文件。"""
|
|
154
206
|
path = _pref_path(repo_root)
|
|
@@ -218,6 +270,13 @@ def _write_runtime_decision(
|
|
|
218
270
|
decisions = context.get("route_decisions")
|
|
219
271
|
if not isinstance(decisions, dict):
|
|
220
272
|
decisions = {}
|
|
273
|
+
# 同一 AI session 可能连续处理多个 Trellis 任务。写入新任务的任一路由时,
|
|
274
|
+
# 先丢弃旧任务的 runtime 决策,避免后续 check 阶段绕过 helper 时误复用上个任务的选择。
|
|
275
|
+
decisions = {
|
|
276
|
+
key: value
|
|
277
|
+
for key, value in decisions.items()
|
|
278
|
+
if isinstance(value, dict) and value.get("task") == current_task
|
|
279
|
+
}
|
|
221
280
|
decision = _decision(target, mode, source, current_task)
|
|
222
281
|
decision["decided_at"] = now
|
|
223
282
|
decisions[target] = decision
|
|
@@ -280,7 +339,7 @@ def read_runtime(args: argparse.Namespace) -> int:
|
|
|
280
339
|
|
|
281
340
|
|
|
282
341
|
def resolve_route(args: argparse.Namespace) -> int:
|
|
283
|
-
"""按 runtime → prefs 的优先级解析 route 决策。"""
|
|
342
|
+
"""按 runtime → prefs → auto-loop 的优先级解析 route 决策。"""
|
|
284
343
|
repo_root = _repo_root()
|
|
285
344
|
if repo_root is None:
|
|
286
345
|
return _print({"status": "miss", "reason": "not-trellis-project"})
|
|
@@ -337,15 +396,45 @@ def resolve_route(args: argparse.Namespace) -> int:
|
|
|
337
396
|
}
|
|
338
397
|
)
|
|
339
398
|
|
|
399
|
+
auto_mode, auto_path, auto_reason = _auto_route_mode(repo_root, context_key, args.target)
|
|
400
|
+
if auto_mode in PREF_MODES[args.target]:
|
|
401
|
+
written_path, auto_decision = _write_runtime_decision(
|
|
402
|
+
repo_root,
|
|
403
|
+
context_key,
|
|
404
|
+
current_task,
|
|
405
|
+
args.target,
|
|
406
|
+
auto_mode,
|
|
407
|
+
"auto-loop",
|
|
408
|
+
)
|
|
409
|
+
return _output(
|
|
410
|
+
args,
|
|
411
|
+
{
|
|
412
|
+
"status": "hit",
|
|
413
|
+
"origin": "auto-loop",
|
|
414
|
+
**_decision_summary(auto_decision),
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"decision": auto_decision,
|
|
418
|
+
"path": _rel_path(repo_root, written_path),
|
|
419
|
+
"auto_path": _rel_path(repo_root, auto_path) if auto_path else None,
|
|
420
|
+
"pref_path": _rel_path(repo_root, _pref_path(repo_root)),
|
|
421
|
+
"context_key": context_key,
|
|
422
|
+
"task": current_task,
|
|
423
|
+
"wrote_runtime": True,
|
|
424
|
+
}
|
|
425
|
+
)
|
|
426
|
+
|
|
340
427
|
return _output(
|
|
341
428
|
args,
|
|
342
429
|
{
|
|
343
430
|
"status": "miss",
|
|
344
|
-
"reason": "no-valid-decision-or-
|
|
431
|
+
"reason": "no-valid-decision-pref-or-auto",
|
|
345
432
|
},
|
|
346
433
|
{
|
|
347
434
|
"path": _rel_path(repo_root, path),
|
|
348
435
|
"pref_path": _rel_path(repo_root, _pref_path(repo_root)),
|
|
436
|
+
"auto_reason": auto_reason,
|
|
437
|
+
"auto_path": _rel_path(repo_root, auto_path) if auto_path else None,
|
|
349
438
|
"context_key": context_key,
|
|
350
439
|
"task": current_task,
|
|
351
440
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: trellis-auto-loop
|
|
3
|
+
description: "启动、恢复和推进 Trellis 自动任务循环。用于用户明确要求 auto loop、自动跑任务、/goal 类似流程、一次跑多个任务、继续自动 run、查看/停止 auto-loop,或压缩恢复后需要从 .trellis/scripts/auto_loop.py 读取下一步。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Trellis Auto Loop
|
|
7
|
+
|
|
8
|
+
用 `.trellis/scripts/auto_loop.py` 驱动一个接近 `/goal` 的任务循环。Python runner 是状态权威;本 skill 只负责把用户意图映射到 runner 命令,并按 runner 返回的 action 调用现有 Trellis workflow / skill / subagent。
|
|
9
|
+
|
|
10
|
+
## 核心规则
|
|
11
|
+
|
|
12
|
+
- 只有用户明确要求自动跑、auto loop、goal-like、继续自动 run、批量任务队列时才启动或恢复;不要把普通实现请求自动升级为 auto-loop。
|
|
13
|
+
- 每次开始、恢复、压缩后继续时,先运行 runner 的 `resume` 或 `next`,不要凭聊天摘要推断下一步。
|
|
14
|
+
- 每完成一个 action,必须用 `record --action <next 返回的 action>` 精确写回结果;runner 会拒绝缺失或不匹配的 action。写回后立即再调用 `next`,直到 `done`、`blocked` 或需要用户决策。
|
|
15
|
+
- 默认 profile 是 `commit-only`:自动推进到本地 commit,不 push、不发布、不归档。
|
|
16
|
+
- 多任务只按用户显式给出的任务顺序执行;同一 worktree 不并发。
|
|
17
|
+
- route 临时授权写在 auto-loop runtime 中,低于个人 `.trellis/.route-prefs.tmp`;不要写个人偏好。
|
|
18
|
+
- planning start gate 会按有效 route 判断 JSONL 是否必需:inline / check-all-inline 可不因 seed-only JSONL 停住;个人默认 subagent 仍优先于 auto inline 授权并要求 curated context。
|
|
19
|
+
- 代码提交必须走 `trellis-push` 的 commit-only 语义;不要裸 `git commit` / `git push`。
|
|
20
|
+
|
|
21
|
+
## 启动
|
|
22
|
+
|
|
23
|
+
用户给了任务列表时,按原顺序传入;用户只说当前任务时,用 `task.py current --source` 的当前任务。
|
|
24
|
+
|
|
25
|
+
子代理可用的 workflow 默认写入临时 route 授权:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python3 ./.trellis/scripts/auto_loop.py start \
|
|
29
|
+
--tasks <task> [<task> ...] \
|
|
30
|
+
--profile commit-only \
|
|
31
|
+
--route-implement subagent \
|
|
32
|
+
--route-check check-all-subagent
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
inline-only 场景改用:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python3 ./.trellis/scripts/auto_loop.py start \
|
|
39
|
+
--tasks <task> [<task> ...] \
|
|
40
|
+
--profile commit-only \
|
|
41
|
+
--route-implement inline \
|
|
42
|
+
--route-check check-all-inline
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
如果用户个人 `.trellis/.route-prefs.tmp` 存在,`trellis-route` 会优先使用个人偏好;auto 授权只负责 prefs miss 时减少询问。
|
|
46
|
+
|
|
47
|
+
启动后立即运行:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python3 ./.trellis/scripts/auto_loop.py next
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 恢复
|
|
54
|
+
|
|
55
|
+
压缩、重开会话、用户说“继续自动跑 / continue auto loop”时:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python3 ./.trellis/scripts/auto_loop.py resume
|
|
59
|
+
python3 ./.trellis/scripts/auto_loop.py next
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`resume_capsule` 只用于展示;下一步以 `next` 返回的 JSON 为准。
|
|
63
|
+
|
|
64
|
+
## Action 映射
|
|
65
|
+
|
|
66
|
+
| runner action | 主 agent 动作 | 成功 record |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| `refresh_brief` | 使用 `trellis-task-brief` 生成并展示 brief | `record --action refresh_brief --result ok` |
|
|
69
|
+
| `start_task` | 执行返回的 `task.py start ...` 命令 | `record --action start_task --result ok` |
|
|
70
|
+
| `run_implement` | 进入 Phase 2.1,先用 `trellis-route(target=implement)` 决定 inline/subagent,再实现 | `record --action run_implement --result ok` |
|
|
71
|
+
| `run_check_all` | 进入 Phase 2.2,先用 `trellis-route(target=check)`,执行 check-all | `record --action run_check_all --result ok` |
|
|
72
|
+
| `run_fix` | 根据 `last_failure` 修复,复用当前任务 implement route | `record --action run_fix --result ok` |
|
|
73
|
+
| `run_recheck` | 复用当前任务 check route,重新 check-all | `record --action run_recheck --result ok` |
|
|
74
|
+
| `run_spec_update` | 有代码/测试证据时用 `trellis-update-spec`;无必要更新也 record ok | `record --action run_spec_update --result ok` |
|
|
75
|
+
| `commit_only` | 使用 `trellis-push` commit-only auto-loop 预授权路径,只提交当前任务可归属文件 | `record --action commit_only --result ok --commit <hash>` |
|
|
76
|
+
|
|
77
|
+
失败时写回:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python3 ./.trellis/scripts/auto_loop.py record \
|
|
81
|
+
--action <action> \
|
|
82
|
+
--result failed \
|
|
83
|
+
--failure-type <type> \
|
|
84
|
+
--summary "<失败摘要>" \
|
|
85
|
+
--files <file> [<file> ...]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
需要用户产品决策或越权时写回 blocked:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python3 ./.trellis/scripts/auto_loop.py record \
|
|
92
|
+
--action <action> \
|
|
93
|
+
--result blocked \
|
|
94
|
+
--failure-type <type> \
|
|
95
|
+
--summary "<阻塞原因>"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
runner 会按 3 轮 fix/recheck 预算决定继续、跳过当前任务或结束队列。
|
|
99
|
+
|
|
100
|
+
## Commit-Only 预授权
|
|
101
|
+
|
|
102
|
+
auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本地提交”的一次性预授权。只有同时满足这些条件时,`trellis-push` 可以跳过二次聊天确认:
|
|
103
|
+
|
|
104
|
+
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,且 `outstanding_action.action=commit_only`、`outstanding_action.task` 等于当前活动任务。
|
|
105
|
+
- profile 是 `commit-only`。
|
|
106
|
+
- 模式是 commit-only,不 push、不 merge、不发布、不归档。
|
|
107
|
+
- 提交计划只包含当前任务可归属文件;未识别 dirty 文件保留未提交并写入结果摘要。
|
|
108
|
+
- 执行前复核 git 状态仍与计划一致。
|
|
109
|
+
|
|
110
|
+
如果计划包含未识别 staged 文件、冲突、push/merge/release/archive、真实外部系统或生产数据效果,停止并把当前任务记为 blocked。
|
|
111
|
+
|
|
112
|
+
## 状态与停止
|
|
113
|
+
|
|
114
|
+
查看:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
python3 ./.trellis/scripts/auto_loop.py status
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
停止:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python3 ./.trellis/scripts/auto_loop.py stop --reason "<原因>"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 不要做
|
|
127
|
+
|
|
128
|
+
- 不要手写或手改 `.trellis/.runtime/auto-loop/*.json`。
|
|
129
|
+
- 不要把 `.trellis/.runtime/` 或 `.trellis/.route-prefs.tmp` 加入提交。
|
|
130
|
+
- 不要在 auto-loop 外把普通 check 的 post-check stop gate 当成可跳过。
|
|
131
|
+
- 不要为模糊需求自动创建任务并开跑;先回到 Trellis planning。
|
|
@@ -8,6 +8,8 @@ description: "提交并推送配置仓库,可选合并到目标分支,并同
|
|
|
8
8
|
|
|
9
9
|
核心原则:**先计划、一次确认、后执行**。在任何 `git add`、`git commit`、`git push`、`git merge` 之前,必须先展示完整执行计划,并获得用户确认。
|
|
10
10
|
|
|
11
|
+
例外:当 `trellis-auto-loop` 已显式以 `profile=commit-only` 启动,且 runner 当前有 `outstanding_action.action=commit_only` 时,用户启动 auto-loop 本身就是本次 run 内任务相关本地提交的预授权。此时仍必须生成并自检完整计划,但如果计划只包含当前任务可归属文件、模式为 commit-only、不会 push/merge/release/archive,并且执行后会把 commit hash 回写 runner,可以跳过二次聊天确认直接执行。
|
|
12
|
+
|
|
11
13
|
支持多仓库(frontend / backend 等),merge 目标分支记录在 `.trellis/config.yaml` 的 `packages.<name>.merge_target` 中。
|
|
12
14
|
|
|
13
15
|
---
|
|
@@ -62,9 +64,22 @@ Step 6 输出结果
|
|
|
62
64
|
| 重新配置 | 本次允许重新指定 merge 目标,并回写 `merge_target` | `重新配置 push 目标分支` / `reconfigure push` |
|
|
63
65
|
| 临时目标 | 本次临时指定 merge 目标,不修改配置 | `push 到 hotfix 分支` |
|
|
64
66
|
| snapshot-only | 不提交业务代码,只写入 / 同步任务进度快照 | `只更新 snapshot` / `snapshot-only` |
|
|
67
|
+
| auto-loop commit-only | 由 `trellis-auto-loop` runner 的 `commit_only` action 触发,只提交本任务可归属文件,不二次确认、不 push | `trellis-auto-loop` 内部触发 |
|
|
65
68
|
|
|
66
69
|
`snapshot-only` 只在用户明确要求时使用。它仍必须展示统一执行计划;`pushed_commits` 取计划中确认的现有 commit,或按用户说明记录。
|
|
67
70
|
|
|
71
|
+
### 0.1.1 auto-loop commit-only 判定
|
|
72
|
+
|
|
73
|
+
只有同时满足以下条件,才可走 auto-loop 预授权路径:
|
|
74
|
+
|
|
75
|
+
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,profile 为 `commit-only`。
|
|
76
|
+
- status 摘要里的 `outstanding_action.action` 是 `commit_only`,且 `outstanding_action.task` 等于当前活动任务。
|
|
77
|
+
- 本次 `trellis-push` 语义是 commit-only,不包含 push / merge / release / archive。
|
|
78
|
+
- 计划拟提交文件全部能归属当前任务;未识别 dirty 文件不纳入提交。
|
|
79
|
+
- 执行前复核 git 状态与计划一致。
|
|
80
|
+
|
|
81
|
+
任一条件不满足时,不得使用预授权。普通 `trellis-push` 继续走“展示计划并等待确认”的规则。
|
|
82
|
+
|
|
68
83
|
### 0.2 发现候选 Git 仓库
|
|
69
84
|
|
|
70
85
|
读取 `.trellis/config.yaml` 中的 `packages` 配置,但不要把 `git: true` 当作唯一仓库发现规则。`git: true` 主要用于 Trellis session context 展示独立包仓库状态;`trellis-push` 必须以实际 Git root 为准发现可提交仓库:
|
|
@@ -131,7 +146,7 @@ git log <base_branch>..HEAD --oneline
|
|
|
131
146
|
|
|
132
147
|
## Step 2: 生成统一执行计划
|
|
133
148
|
|
|
134
|
-
这是唯一的常规确认点。**确认前禁止执行任何 `git add` / commit / push / merge / task.json 写入。**
|
|
149
|
+
这是唯一的常规确认点。**确认前禁止执行任何 `git add` / commit / push / merge / task.json 写入。** 唯一例外是已满足 Step 0.1.1 的 auto-loop commit-only 预授权;该路径仍要生成计划并执行自检,只是不再等待用户二次确认。
|
|
135
150
|
|
|
136
151
|
### 2.1 生成业务提交计划
|
|
137
152
|
|