flower-trellis 0.4.0-beta.0 → 0.4.0-beta.1
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/enhancements/0.6/.agents/skills/trellis-auto-loop/SKILL.md +20 -18
- package/enhancements/0.6/.agents/skills/trellis-push/SKILL.md +3 -1
- package/enhancements/0.6/.agents/skills/trellis-route/scripts/route_state.py +49 -22
- package/enhancements/0.6/.claude/skills/trellis-auto-loop/SKILL.md +20 -18
- package/enhancements/0.6/.claude/skills/trellis-push/SKILL.md +3 -1
- package/enhancements/0.6/.claude/skills/trellis-route/scripts/route_state.py +49 -22
- package/enhancements/0.6/overrides/workflow-states/in_progress-inline.md +1 -0
- package/enhancements/0.6/overrides/workflow-states/in_progress.md +1 -0
- package/enhancements/0.6/overrides/workflow-states/no_task.md +1 -0
- 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 +16 -1
- package/enhancements/0.6/scripts/auto_loop.py +239 -7
- package/enhancements/0.6/scripts/spec_router.py +417 -0
- package/enhancements/MANIFEST.json +4 -3
- package/package.json +1 -1
- package/src/lib/copy-scripts.js +11 -1
|
@@ -14,35 +14,30 @@ description: "启动、恢复和推进 Trellis 自动任务循环。用于用户
|
|
|
14
14
|
- 每完成一个 action,必须用 `record --action <next 返回的 action>` 精确写回结果;runner 会拒绝缺失或不匹配的 action。写回后立即再调用 `next`,直到 `done`、`blocked` 或需要用户决策。
|
|
15
15
|
- 默认 profile 是 `commit-only`:自动推进到本地 commit,不 push、不发布、不归档。
|
|
16
16
|
- 多任务只按用户显式给出的任务顺序执行;同一 worktree 不并发。
|
|
17
|
-
- route
|
|
18
|
-
-
|
|
17
|
+
- 启动 runner 前先完成 route 准备度判断:已有当前任务 runtime route 决策或个人 `.trellis/.route-prefs.tmp` 时可启动;没有时先进入 `trellis-route` 正常询问 / fallback,写入真实决策后再启动。
|
|
18
|
+
- auto-loop 不默认写 `route_authorization`;如果未来显式传 route 参数,只能表示用户本次明确给出的临时策略,不能当成模型真实执行结果。
|
|
19
19
|
- 代码提交必须走 `trellis-push` 的 commit-only 语义;不要裸 `git commit` / `git push`。
|
|
20
20
|
|
|
21
21
|
## 启动
|
|
22
22
|
|
|
23
23
|
用户给了任务列表时,按原顺序传入;用户只说当前任务时,用 `task.py current --source` 的当前任务。
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
启动前对当前任务执行 route 准备度检查:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
python3
|
|
29
|
-
|
|
30
|
-
--profile commit-only \
|
|
31
|
-
--route-implement subagent \
|
|
32
|
-
--route-check check-all-subagent
|
|
28
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target implement
|
|
29
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target check
|
|
33
30
|
```
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
如果任一 target 返回 `status=miss`,先按 `trellis-route` 的正常 numbered fallback 询问用户并写入 runtime;不要替用户默认 inline 或 subagent。route 准备完成后启动 runner:
|
|
36
33
|
|
|
37
34
|
```bash
|
|
38
35
|
python3 ./.trellis/scripts/auto_loop.py start \
|
|
39
36
|
--tasks <task> [<task> ...] \
|
|
40
|
-
--profile commit-only
|
|
41
|
-
--route-implement inline \
|
|
42
|
-
--route-check check-all-inline
|
|
37
|
+
--profile commit-only
|
|
43
38
|
```
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
多任务队列中,当前任务切换到下一个任务且缺少该任务 route 决策时,回到 `trellis-route` 获取该任务真实选择,再继续 `next` / `record`。个人 `.trellis/.route-prefs.tmp` 会由 `trellis-route` 统一复用并写回 runtime。
|
|
46
41
|
|
|
47
42
|
启动后立即运行:
|
|
48
43
|
|
|
@@ -67,12 +62,12 @@ python3 ./.trellis/scripts/auto_loop.py next
|
|
|
67
62
|
| --- | --- | --- |
|
|
68
63
|
| `refresh_brief` | 使用 `trellis-task-brief` 生成并展示 brief | `record --action refresh_brief --result ok` |
|
|
69
64
|
| `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
|
|
65
|
+
| `run_implement` | 进入 Phase 2.1,先用 `trellis-route(target=implement)` 决定 inline/subagent,再实现 | `record --action run_implement --result ok --route-mode <mode> --route-source <source>` |
|
|
66
|
+
| `run_check_all` | 进入 Phase 2.2,先用 `trellis-route(target=check)`,执行 check-all | `record --action run_check_all --result ok --route-mode <mode> --route-source <source>` |
|
|
67
|
+
| `run_fix` | 根据 `last_failure` 修复,复用当前任务 implement route | `record --action run_fix --result ok --route-mode <mode> --route-source <source>` |
|
|
68
|
+
| `run_recheck` | 复用当前任务 check route,重新 check-all | `record --action run_recheck --result ok --route-mode <mode> --route-source <source>` |
|
|
74
69
|
| `run_spec_update` | 有代码/测试证据时用 `trellis-update-spec`;无必要更新也 record ok | `record --action run_spec_update --result ok` |
|
|
75
|
-
| `commit_only` |
|
|
70
|
+
| `commit_only` | 进入 `trellis-push` commit-only 语义:先由 AI 基于 task artifacts 与 git diff 生成提交计划,只提交当前任务可归属文件 | 执行成功后 `record --action commit_only --result ok --commit <hash>` |
|
|
76
71
|
|
|
77
72
|
失败时写回:
|
|
78
73
|
|
|
@@ -97,6 +92,10 @@ python3 ./.trellis/scripts/auto_loop.py record \
|
|
|
97
92
|
|
|
98
93
|
runner 会按 3 轮 fix/recheck 预算决定继续、跳过当前任务或结束队列。
|
|
99
94
|
|
|
95
|
+
route action 成功回写时必须带上 `trellis-route` 输出里的真实 `mode` / `source`,例如
|
|
96
|
+
`--route-mode inline --route-source route-prefs` 或
|
|
97
|
+
`--route-mode check-all-subagent --route-source trellis-route`;不要写 auto-loop 默认值。
|
|
98
|
+
|
|
100
99
|
## Commit-Only 预授权
|
|
101
100
|
|
|
102
101
|
auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本地提交”的一次性预授权。只有同时满足这些条件时,`trellis-push` 可以跳过二次聊天确认:
|
|
@@ -104,11 +103,14 @@ auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本
|
|
|
104
103
|
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,且 `outstanding_action.action=commit_only`、`outstanding_action.task` 等于当前活动任务。
|
|
105
104
|
- profile 是 `commit-only`。
|
|
106
105
|
- 模式是 commit-only,不 push、不 merge、不发布、不归档。
|
|
106
|
+
- AI 已基于当前任务 artifacts、`git status`、`git diff` 和必要的文件内容生成提交计划,并能说明每个 planned file 为什么属于当前任务。
|
|
107
107
|
- 提交计划只包含当前任务可归属文件;未识别 dirty 文件保留未提交并写入结果摘要。
|
|
108
108
|
- 执行前复核 git 状态仍与计划一致。
|
|
109
109
|
|
|
110
110
|
如果计划包含未识别 staged 文件、冲突、push/merge/release/archive、真实外部系统或生产数据效果,停止并把当前任务记为 blocked。
|
|
111
111
|
|
|
112
|
+
不要用脚本基于时间差或 dirty baseline 猜测文件归属;语义归属由 AI 负责判断,`trellis-push` 负责展示/复核计划、精确暂存 planned files、执行本地 commit,并把 commit hash 回写 runner。预检不安全时只把当前队列项记为 blocked/skipped,并让 auto-loop 可继续后续任务。
|
|
113
|
+
|
|
112
114
|
## 状态与停止
|
|
113
115
|
|
|
114
116
|
查看:
|
|
@@ -8,7 +8,7 @@ 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
|
|
11
|
+
例外:当 `trellis-auto-loop` 已显式以 `profile=commit-only` 启动,且 runner 当前有 `outstanding_action.action=commit_only` 时,用户启动 auto-loop 本身就是本次 run 内任务相关本地提交的预授权。此时仍必须由 AI 生成并自检提交计划,但可跳过二次聊天确认;计划只允许 commit-only、不 push/merge/release/archive,并在成功后把 commit hash 回写 runner。预检不安全时只标记当前 auto-loop item blocked/skipped,后续队列仍可继续。
|
|
12
12
|
|
|
13
13
|
支持多仓库(frontend / backend 等),merge 目标分支记录在 `.trellis/config.yaml` 的 `packages.<name>.merge_target` 中。
|
|
14
14
|
|
|
@@ -80,6 +80,8 @@ Step 6 输出结果
|
|
|
80
80
|
|
|
81
81
|
任一条件不满足时,不得使用预授权。普通 `trellis-push` 继续走“展示计划并等待确认”的规则。
|
|
82
82
|
|
|
83
|
+
auto-loop 预授权路径不使用额外提交 helper。AI 负责根据当前任务 artifacts、`git status`、`git diff` 和必要的文件内容判断文件归属,输出 planned files / retained files / commit message / 归属理由;`trellis-push` 负责边界复核:当前 action/profile/task 匹配、staged 区为空、无冲突、planned files 当前 dirty、planned files 不含 `.trellis/.runtime/`、`.trellis/.route-prefs.tmp`、其他任务目录或未解释文件。通过后只 `git add` planned files 并执行本地 commit,随后回写 `auto_loop.py record --action commit_only --result ok --commit <hash> ...`。预检失败时回写 `record --result blocked`,该 blocked 只影响当前 item;auto-loop runner 后续 `next` 应继续寻找后续 pending 任务。只有 merge/rebase 冲突、repo 状态不可读、脚本损坏或用户明确 stop 才停止整个 run。
|
|
84
|
+
|
|
83
85
|
### 0.2 发现候选 Git 仓库
|
|
84
86
|
|
|
85
87
|
读取 `.trellis/config.yaml` 中的 `packages` 配置,但不要把 `git: true` 当作唯一仓库发现规则。`git: true` 主要用于 Trellis session context 展示独立包仓库状态;`trellis-push` 必须以实际 Git root 为准发现可提交仓库:
|
|
@@ -160,36 +160,63 @@ def _read_prefs(repo_root: Path) -> dict[str, str]:
|
|
|
160
160
|
return prefs
|
|
161
161
|
|
|
162
162
|
|
|
163
|
+
def _running_auto_run_paths(repo_root: Path) -> list[Path]:
|
|
164
|
+
"""扫描当前项目内所有 running auto-loop run。"""
|
|
165
|
+
running: list[Path] = []
|
|
166
|
+
for path in sorted(_auto_loop_dir(repo_root).glob("auto-*.json")):
|
|
167
|
+
state = _read_json(path)
|
|
168
|
+
if state.get("status") == "running":
|
|
169
|
+
running.append(path)
|
|
170
|
+
return running
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _auto_state_path(repo_root: Path, run_id: Any) -> Path | None:
|
|
174
|
+
"""把 run id 转成状态文件路径,非法值返回 None。"""
|
|
175
|
+
if not isinstance(run_id, str) or not run_id.strip():
|
|
176
|
+
return None
|
|
177
|
+
return _auto_loop_dir(repo_root) / f"{run_id.strip()}.json"
|
|
178
|
+
|
|
179
|
+
|
|
163
180
|
def _auto_route_mode(repo_root: Path, context_key: str, target: str) -> tuple[str | None, Path | None, str | None]:
|
|
164
|
-
"""读取当前 auto-loop run 的临时 route 授权。
|
|
181
|
+
"""读取当前 running auto-loop run 的临时 route 授权。
|
|
165
182
|
|
|
166
183
|
auto 授权低于个人 `.route-prefs.tmp`,只在当前 session runtime 绑定了
|
|
167
|
-
`current_auto_run`,或全局 current
|
|
168
|
-
|
|
184
|
+
running `current_auto_run`,或全局 current 指针能指向 running run 时生效。
|
|
185
|
+
如果这些指针 stale,则忽略 stale pointer,并 fallback 到唯一 running run。
|
|
169
186
|
"""
|
|
170
187
|
session_path = _session_path(repo_root, context_key)
|
|
171
188
|
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
189
|
candidate_paths: list[Path] = []
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
+
stale_paths: list[Path] = []
|
|
191
|
+
|
|
192
|
+
for run_id in (session.get("current_auto_run"), _read_json(_auto_loop_pointer(repo_root)).get("run_id")):
|
|
193
|
+
path = _auto_state_path(repo_root, run_id)
|
|
194
|
+
if path is None:
|
|
195
|
+
continue
|
|
196
|
+
state = _read_json(path)
|
|
197
|
+
if state.get("status") == "running":
|
|
198
|
+
candidate_paths.append(path)
|
|
199
|
+
else:
|
|
200
|
+
stale_paths.append(path)
|
|
201
|
+
|
|
202
|
+
if not candidate_paths:
|
|
203
|
+
candidate_paths = _running_auto_run_paths(repo_root)
|
|
204
|
+
unique_paths = []
|
|
205
|
+
seen: set[str] = set()
|
|
206
|
+
for path in candidate_paths:
|
|
207
|
+
key = str(path)
|
|
208
|
+
if key in seen:
|
|
209
|
+
continue
|
|
210
|
+
seen.add(key)
|
|
211
|
+
unique_paths.append(path)
|
|
212
|
+
if len(unique_paths) != 1:
|
|
213
|
+
reason = "no-unique-auto-run"
|
|
214
|
+
if stale_paths and not unique_paths:
|
|
215
|
+
reason = "stale-auto-run-pointer"
|
|
216
|
+
return None, stale_paths[0] if stale_paths else None, reason
|
|
217
|
+
|
|
218
|
+
path = unique_paths[0]
|
|
190
219
|
state = _read_json(path)
|
|
191
|
-
if state.get("status") != "running":
|
|
192
|
-
return None, path, "auto-run-not-running"
|
|
193
220
|
|
|
194
221
|
auth = state.get("route_authorization")
|
|
195
222
|
if not isinstance(auth, dict):
|
|
@@ -14,35 +14,30 @@ description: "启动、恢复和推进 Trellis 自动任务循环。用于用户
|
|
|
14
14
|
- 每完成一个 action,必须用 `record --action <next 返回的 action>` 精确写回结果;runner 会拒绝缺失或不匹配的 action。写回后立即再调用 `next`,直到 `done`、`blocked` 或需要用户决策。
|
|
15
15
|
- 默认 profile 是 `commit-only`:自动推进到本地 commit,不 push、不发布、不归档。
|
|
16
16
|
- 多任务只按用户显式给出的任务顺序执行;同一 worktree 不并发。
|
|
17
|
-
- route
|
|
18
|
-
-
|
|
17
|
+
- 启动 runner 前先完成 route 准备度判断:已有当前任务 runtime route 决策或个人 `.trellis/.route-prefs.tmp` 时可启动;没有时先进入 `trellis-route` 正常询问 / fallback,写入真实决策后再启动。
|
|
18
|
+
- auto-loop 不默认写 `route_authorization`;如果未来显式传 route 参数,只能表示用户本次明确给出的临时策略,不能当成模型真实执行结果。
|
|
19
19
|
- 代码提交必须走 `trellis-push` 的 commit-only 语义;不要裸 `git commit` / `git push`。
|
|
20
20
|
|
|
21
21
|
## 启动
|
|
22
22
|
|
|
23
23
|
用户给了任务列表时,按原顺序传入;用户只说当前任务时,用 `task.py current --source` 的当前任务。
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
启动前对当前任务执行 route 准备度检查:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
python3
|
|
29
|
-
|
|
30
|
-
--profile commit-only \
|
|
31
|
-
--route-implement subagent \
|
|
32
|
-
--route-check check-all-subagent
|
|
28
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target implement
|
|
29
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target check
|
|
33
30
|
```
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
如果任一 target 返回 `status=miss`,先按 `trellis-route` 的正常 numbered fallback 询问用户并写入 runtime;不要替用户默认 inline 或 subagent。route 准备完成后启动 runner:
|
|
36
33
|
|
|
37
34
|
```bash
|
|
38
35
|
python3 ./.trellis/scripts/auto_loop.py start \
|
|
39
36
|
--tasks <task> [<task> ...] \
|
|
40
|
-
--profile commit-only
|
|
41
|
-
--route-implement inline \
|
|
42
|
-
--route-check check-all-inline
|
|
37
|
+
--profile commit-only
|
|
43
38
|
```
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
多任务队列中,当前任务切换到下一个任务且缺少该任务 route 决策时,回到 `trellis-route` 获取该任务真实选择,再继续 `next` / `record`。个人 `.trellis/.route-prefs.tmp` 会由 `trellis-route` 统一复用并写回 runtime。
|
|
46
41
|
|
|
47
42
|
启动后立即运行:
|
|
48
43
|
|
|
@@ -67,12 +62,12 @@ python3 ./.trellis/scripts/auto_loop.py next
|
|
|
67
62
|
| --- | --- | --- |
|
|
68
63
|
| `refresh_brief` | 使用 `trellis-task-brief` 生成并展示 brief | `record --action refresh_brief --result ok` |
|
|
69
64
|
| `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
|
|
65
|
+
| `run_implement` | 进入 Phase 2.1,先用 `trellis-route(target=implement)` 决定 inline/subagent,再实现 | `record --action run_implement --result ok --route-mode <mode> --route-source <source>` |
|
|
66
|
+
| `run_check_all` | 进入 Phase 2.2,先用 `trellis-route(target=check)`,执行 check-all | `record --action run_check_all --result ok --route-mode <mode> --route-source <source>` |
|
|
67
|
+
| `run_fix` | 根据 `last_failure` 修复,复用当前任务 implement route | `record --action run_fix --result ok --route-mode <mode> --route-source <source>` |
|
|
68
|
+
| `run_recheck` | 复用当前任务 check route,重新 check-all | `record --action run_recheck --result ok --route-mode <mode> --route-source <source>` |
|
|
74
69
|
| `run_spec_update` | 有代码/测试证据时用 `trellis-update-spec`;无必要更新也 record ok | `record --action run_spec_update --result ok` |
|
|
75
|
-
| `commit_only` |
|
|
70
|
+
| `commit_only` | 进入 `trellis-push` commit-only 语义:先由 AI 基于 task artifacts 与 git diff 生成提交计划,只提交当前任务可归属文件 | 执行成功后 `record --action commit_only --result ok --commit <hash>` |
|
|
76
71
|
|
|
77
72
|
失败时写回:
|
|
78
73
|
|
|
@@ -97,6 +92,10 @@ python3 ./.trellis/scripts/auto_loop.py record \
|
|
|
97
92
|
|
|
98
93
|
runner 会按 3 轮 fix/recheck 预算决定继续、跳过当前任务或结束队列。
|
|
99
94
|
|
|
95
|
+
route action 成功回写时必须带上 `trellis-route` 输出里的真实 `mode` / `source`,例如
|
|
96
|
+
`--route-mode inline --route-source route-prefs` 或
|
|
97
|
+
`--route-mode check-all-subagent --route-source trellis-route`;不要写 auto-loop 默认值。
|
|
98
|
+
|
|
100
99
|
## Commit-Only 预授权
|
|
101
100
|
|
|
102
101
|
auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本地提交”的一次性预授权。只有同时满足这些条件时,`trellis-push` 可以跳过二次聊天确认:
|
|
@@ -104,11 +103,14 @@ auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本
|
|
|
104
103
|
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,且 `outstanding_action.action=commit_only`、`outstanding_action.task` 等于当前活动任务。
|
|
105
104
|
- profile 是 `commit-only`。
|
|
106
105
|
- 模式是 commit-only,不 push、不 merge、不发布、不归档。
|
|
106
|
+
- AI 已基于当前任务 artifacts、`git status`、`git diff` 和必要的文件内容生成提交计划,并能说明每个 planned file 为什么属于当前任务。
|
|
107
107
|
- 提交计划只包含当前任务可归属文件;未识别 dirty 文件保留未提交并写入结果摘要。
|
|
108
108
|
- 执行前复核 git 状态仍与计划一致。
|
|
109
109
|
|
|
110
110
|
如果计划包含未识别 staged 文件、冲突、push/merge/release/archive、真实外部系统或生产数据效果,停止并把当前任务记为 blocked。
|
|
111
111
|
|
|
112
|
+
不要用脚本基于时间差或 dirty baseline 猜测文件归属;语义归属由 AI 负责判断,`trellis-push` 负责展示/复核计划、精确暂存 planned files、执行本地 commit,并把 commit hash 回写 runner。预检不安全时只把当前队列项记为 blocked/skipped,并让 auto-loop 可继续后续任务。
|
|
113
|
+
|
|
112
114
|
## 状态与停止
|
|
113
115
|
|
|
114
116
|
查看:
|
|
@@ -8,7 +8,7 @@ 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
|
|
11
|
+
例外:当 `trellis-auto-loop` 已显式以 `profile=commit-only` 启动,且 runner 当前有 `outstanding_action.action=commit_only` 时,用户启动 auto-loop 本身就是本次 run 内任务相关本地提交的预授权。此时仍必须由 AI 生成并自检提交计划,但可跳过二次聊天确认;计划只允许 commit-only、不 push/merge/release/archive,并在成功后把 commit hash 回写 runner。预检不安全时只标记当前 auto-loop item blocked/skipped,后续队列仍可继续。
|
|
12
12
|
|
|
13
13
|
支持多仓库(frontend / backend 等),merge 目标分支记录在 `.trellis/config.yaml` 的 `packages.<name>.merge_target` 中。
|
|
14
14
|
|
|
@@ -80,6 +80,8 @@ Step 6 输出结果
|
|
|
80
80
|
|
|
81
81
|
任一条件不满足时,不得使用预授权。普通 `trellis-push` 继续走“展示计划并等待确认”的规则。
|
|
82
82
|
|
|
83
|
+
auto-loop 预授权路径不使用额外提交 helper。AI 负责根据当前任务 artifacts、`git status`、`git diff` 和必要的文件内容判断文件归属,输出 planned files / retained files / commit message / 归属理由;`trellis-push` 负责边界复核:当前 action/profile/task 匹配、staged 区为空、无冲突、planned files 当前 dirty、planned files 不含 `.trellis/.runtime/`、`.trellis/.route-prefs.tmp`、其他任务目录或未解释文件。通过后只 `git add` planned files 并执行本地 commit,随后回写 `auto_loop.py record --action commit_only --result ok --commit <hash> ...`。预检失败时回写 `record --result blocked`,该 blocked 只影响当前 item;auto-loop runner 后续 `next` 应继续寻找后续 pending 任务。只有 merge/rebase 冲突、repo 状态不可读、脚本损坏或用户明确 stop 才停止整个 run。
|
|
84
|
+
|
|
83
85
|
### 0.2 发现候选 Git 仓库
|
|
84
86
|
|
|
85
87
|
读取 `.trellis/config.yaml` 中的 `packages` 配置,但不要把 `git: true` 当作唯一仓库发现规则。`git: true` 主要用于 Trellis session context 展示独立包仓库状态;`trellis-push` 必须以实际 Git root 为准发现可提交仓库:
|
|
@@ -160,36 +160,63 @@ def _read_prefs(repo_root: Path) -> dict[str, str]:
|
|
|
160
160
|
return prefs
|
|
161
161
|
|
|
162
162
|
|
|
163
|
+
def _running_auto_run_paths(repo_root: Path) -> list[Path]:
|
|
164
|
+
"""扫描当前项目内所有 running auto-loop run。"""
|
|
165
|
+
running: list[Path] = []
|
|
166
|
+
for path in sorted(_auto_loop_dir(repo_root).glob("auto-*.json")):
|
|
167
|
+
state = _read_json(path)
|
|
168
|
+
if state.get("status") == "running":
|
|
169
|
+
running.append(path)
|
|
170
|
+
return running
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _auto_state_path(repo_root: Path, run_id: Any) -> Path | None:
|
|
174
|
+
"""把 run id 转成状态文件路径,非法值返回 None。"""
|
|
175
|
+
if not isinstance(run_id, str) or not run_id.strip():
|
|
176
|
+
return None
|
|
177
|
+
return _auto_loop_dir(repo_root) / f"{run_id.strip()}.json"
|
|
178
|
+
|
|
179
|
+
|
|
163
180
|
def _auto_route_mode(repo_root: Path, context_key: str, target: str) -> tuple[str | None, Path | None, str | None]:
|
|
164
|
-
"""读取当前 auto-loop run 的临时 route 授权。
|
|
181
|
+
"""读取当前 running auto-loop run 的临时 route 授权。
|
|
165
182
|
|
|
166
183
|
auto 授权低于个人 `.route-prefs.tmp`,只在当前 session runtime 绑定了
|
|
167
|
-
`current_auto_run`,或全局 current
|
|
168
|
-
|
|
184
|
+
running `current_auto_run`,或全局 current 指针能指向 running run 时生效。
|
|
185
|
+
如果这些指针 stale,则忽略 stale pointer,并 fallback 到唯一 running run。
|
|
169
186
|
"""
|
|
170
187
|
session_path = _session_path(repo_root, context_key)
|
|
171
188
|
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
189
|
candidate_paths: list[Path] = []
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
+
stale_paths: list[Path] = []
|
|
191
|
+
|
|
192
|
+
for run_id in (session.get("current_auto_run"), _read_json(_auto_loop_pointer(repo_root)).get("run_id")):
|
|
193
|
+
path = _auto_state_path(repo_root, run_id)
|
|
194
|
+
if path is None:
|
|
195
|
+
continue
|
|
196
|
+
state = _read_json(path)
|
|
197
|
+
if state.get("status") == "running":
|
|
198
|
+
candidate_paths.append(path)
|
|
199
|
+
else:
|
|
200
|
+
stale_paths.append(path)
|
|
201
|
+
|
|
202
|
+
if not candidate_paths:
|
|
203
|
+
candidate_paths = _running_auto_run_paths(repo_root)
|
|
204
|
+
unique_paths = []
|
|
205
|
+
seen: set[str] = set()
|
|
206
|
+
for path in candidate_paths:
|
|
207
|
+
key = str(path)
|
|
208
|
+
if key in seen:
|
|
209
|
+
continue
|
|
210
|
+
seen.add(key)
|
|
211
|
+
unique_paths.append(path)
|
|
212
|
+
if len(unique_paths) != 1:
|
|
213
|
+
reason = "no-unique-auto-run"
|
|
214
|
+
if stale_paths and not unique_paths:
|
|
215
|
+
reason = "stale-auto-run-pointer"
|
|
216
|
+
return None, stale_paths[0] if stale_paths else None, reason
|
|
217
|
+
|
|
218
|
+
path = unique_paths[0]
|
|
190
219
|
state = _read_json(path)
|
|
191
|
-
if state.get("status") != "running":
|
|
192
|
-
return None, path, "auto-run-not-running"
|
|
193
220
|
|
|
194
221
|
auth = state.get("route_authorization")
|
|
195
222
|
if not isinstance(auth, dict):
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
HIGHEST PRIORITY SKILL-GARDEN STATE GUARD (in_progress-inline):
|
|
3
3
|
This state block is a breadcrumb; the top-level skill-garden hub is the source of truth for route details.
|
|
4
4
|
Before the first implement route, read `<task>/brief.md` if present and restate the task brief in chat. If it is missing, read the task artifacts and suggest backfilling brief; do not silently rely on memory.
|
|
5
|
+
Before procedural or high-impact actions, run `.trellis/scripts/spec_router.py` with a short query describing the intended action and read any matched SOP/spec before acting.
|
|
5
6
|
Inline workflow-state is not an inline route decision. At Phase 2.1/2.2, reuse only an explicit target-matched `route_decision`; otherwise MUST load/read/use `trellis-route(implement|check)` (or its local `SKILL.md`) to resolve session runtime state/prefs, write the resolved decision, or show numbered fallback and wait.
|
|
6
7
|
Plain preferences, ordinary summaries, `codex-mode`, raw `.runtime` files, and empty/old prefs are not route evidence by themselves; only `trellis-route` may validate runtime route state.
|
|
7
8
|
User reselect/override/use-X-this-time/clear-default wins over remembered route evidence, runtime state, and prefs.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
HIGHEST PRIORITY SKILL-GARDEN STATE GUARD (in_progress):
|
|
3
3
|
This state block is a breadcrumb; the top-level skill-garden hub is the source of truth for route details.
|
|
4
4
|
Before the first implement route, read `<task>/brief.md` if present and restate the task brief in chat. If it is missing, read the task artifacts and suggest backfilling brief; do not silently rely on memory.
|
|
5
|
+
Before procedural or high-impact actions, run `.trellis/scripts/spec_router.py` with a short query describing the intended action and read any matched SOP/spec before acting.
|
|
5
6
|
At Phase 2.1/2.2, reuse only an explicit target-matched `route_decision`; otherwise MUST load/read/use `trellis-route(implement|check)` (or its local `SKILL.md`) to resolve session runtime state/prefs, write the resolved decision, or show numbered fallback and wait.
|
|
6
7
|
Plain preferences, ordinary summaries, `codex-mode`, raw `.runtime` files, and empty/old prefs are not route evidence by themselves; only `trellis-route` may validate runtime route state.
|
|
7
8
|
User reselect/override/use-X-this-time/clear-default wins over remembered route evidence, runtime state, and prefs.
|
|
@@ -3,6 +3,7 @@ HIGHEST PRIORITY SKILL-GARDEN STATE GUARD (no_task):
|
|
|
3
3
|
Creating or resuming a task is not implementation permission.
|
|
4
4
|
After PRD is ready and the task is started, the next implementation action is Phase 2.1 `trellis-route(implement)` unless a valid current-task implement route decision already exists.
|
|
5
5
|
If no active task exists, scan `.trellis/tasks/*/task.json` once per session for in-progress tasks with `last_push_snapshot`; surface `completed_steps` + `next_step` and suggest rebinding the active task before resuming.
|
|
6
|
+
Before procedural or high-impact actions, run `.trellis/scripts/spec_router.py` with a short query describing the intended action and read any matched SOP/spec before acting.
|
|
6
7
|
Do NOT call the harness built-in plan mode (`EnterPlanMode` / `ExitPlanMode`) for Trellis planning. It is not a substitute for Trellis task-creation consent, Trellis planning, or the route gate. For complex work, classify the turn, ask for task-creation consent, then use `trellis-brainstorm`.
|
|
7
8
|
If the turn is a meta edit to Trellis itself and Trellis tracking would be overkill, say so and ask to skip Trellis; never silently swap built-in plan mode in for the consent gate.
|
|
8
9
|
<!-- END skill-garden workflow-state no_task v0.6 -->
|
|
@@ -4,5 +4,6 @@ Planning is not implementation permission.
|
|
|
4
4
|
Complete prd.md + required context first.
|
|
5
5
|
If the active workflow later routes to sub-agent execution, required context includes real curated entries in both `implement.jsonl` and `check.jsonl`; the seed `_example` row alone is not ready.
|
|
6
6
|
Before `task.py start`, use `trellis-task-brief` to refresh `brief.md` from the latest task artifacts and display it in chat for review.
|
|
7
|
+
Before procedural or high-impact actions, run `.trellis/scripts/spec_router.py` with a short query describing the intended action and read any matched SOP/spec before acting.
|
|
7
8
|
After status becomes in_progress, next action = `trellis-route(implement)`, not direct edits.
|
|
8
9
|
<!-- END skill-garden workflow-state planning_inline v0.6 -->
|
|
@@ -4,5 +4,6 @@ Planning is not implementation permission.
|
|
|
4
4
|
Complete prd.md + required context first.
|
|
5
5
|
For sub-agent-dispatch platforms, required context includes real curated entries in both `implement.jsonl` and `check.jsonl`; the seed `_example` row alone is not ready.
|
|
6
6
|
Before `task.py start`, use `trellis-task-brief` to refresh `brief.md` from the latest task artifacts and display it in chat for review.
|
|
7
|
+
Before procedural or high-impact actions, run `.trellis/scripts/spec_router.py` with a short query describing the intended action and read any matched SOP/spec before acting.
|
|
7
8
|
After status becomes in_progress, next action = `trellis-route(implement)`, not direct edits.
|
|
8
9
|
<!-- END skill-garden workflow-state planning v0.6 -->
|
|
@@ -6,10 +6,25 @@
|
|
|
6
6
|
|
|
7
7
|
**Priority**: This hub overrides any conflicting Trellis workflow, skill, or command text for the scoped behaviors below.
|
|
8
8
|
|
|
9
|
-
**Scope**: Phase 1.4 task brief handoff, Phase 2.1 implement routing, Phase 2.2 check/check-all routing, current-task route reuse, post-check stop, auto-loop commit-only preauthorization, Phase 3.4 trellis-push, explicit Phase 3.5 finish-work bookkeeping, and push-progress recovery. State blocks should keep one short skill-garden sentinel; long-form rules live here.
|
|
9
|
+
**Scope**: project knowledge discovery for procedural/high-impact actions, Phase 1.4 task brief handoff, Phase 2.1 implement routing, Phase 2.2 check/check-all routing, current-task route reuse, post-check stop, auto-loop commit-only preauthorization, Phase 3.4 trellis-push, explicit Phase 3.5 finish-work bookkeeping, and push-progress recovery. State blocks should keep one short skill-garden sentinel; long-form rules live here.
|
|
10
10
|
|
|
11
11
|
**Mechanical rule**: use this hub as the source of truth. Do not add separate top-level skill-garden override sections or multiple skill-garden sentinels inside the same `workflow-state:*` block.
|
|
12
12
|
|
|
13
|
+
#### Project Knowledge Discovery
|
|
14
|
+
|
|
15
|
+
Before procedural or high-impact actions, run project knowledge discovery:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python3 ./.trellis/scripts/spec_router.py "<short query describing the intended action>"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Build the query from the current user request plus relevant immediate context:
|
|
22
|
+
the intended action, commands about to run, files or systems involved, package/layer,
|
|
23
|
+
and domain words such as release, publish, deploy, migration, config, CI, workflow,
|
|
24
|
+
hooks, rollback, data fix, or destructive command.
|
|
25
|
+
|
|
26
|
+
Read any matched SOP/spec files before acting; if nothing matches, continue normally.
|
|
27
|
+
|
|
13
28
|
#### Task Brief Handoff
|
|
14
29
|
|
|
15
30
|
Before Phase 1.4 `task.py start`, use `trellis-task-brief` to refresh `<task>/brief.md` from latest task artifacts, display it in chat, and wait for user confirmation.
|