flower-trellis 0.4.0-beta.0 → 0.4.0-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.
- package/enhancements/0.6/.agents/skills/trellis-auto-loop/SKILL.md +63 -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 +63 -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 +18 -1
- package/enhancements/0.6/scripts/auto_loop.py +581 -44
- package/enhancements/0.6/scripts/spec_router.py +462 -0
- package/enhancements/MANIFEST.json +4 -3
- package/package.json +1 -1
- package/src/lib/copy-scripts.js +11 -1
|
@@ -12,37 +12,58 @@ description: "启动、恢复和推进 Trellis 自动任务循环。用于用户
|
|
|
12
12
|
- 只有用户明确要求自动跑、auto loop、goal-like、继续自动 run、批量任务队列时才启动或恢复;不要把普通实现请求自动升级为 auto-loop。
|
|
13
13
|
- 每次开始、恢复、压缩后继续时,先运行 runner 的 `resume` 或 `next`,不要凭聊天摘要推断下一步。
|
|
14
14
|
- 每完成一个 action,必须用 `record --action <next 返回的 action>` 精确写回结果;runner 会拒绝缺失或不匹配的 action。写回后立即再调用 `next`,直到 `done`、`blocked` 或需要用户决策。
|
|
15
|
+
- run 进入 `blocked` 后不要用 `start --force` 新建 run 来纠正参数;先补齐缺失 route/context,然后用 `retry-blocked` 在同一个 run 内恢复。
|
|
16
|
+
- runner 默认输出是紧凑 JSON,只包含当前 action、队列计数、简短 blocked/pending/completed 列表和最近少量决策摘要;排障时才给 `status` / `resume` / `next` / `record` / `retry-blocked` 加 `--verbose` 读取完整 item、blocked detail 和 decision data。
|
|
15
17
|
- 默认 profile 是 `commit-only`:自动推进到本地 commit,不 push、不发布、不归档。
|
|
16
18
|
- 多任务只按用户显式给出的任务顺序执行;同一 worktree 不并发。
|
|
17
|
-
- route
|
|
18
|
-
-
|
|
19
|
+
- 启动 runner 前先完成 route 准备度判断:已有当前任务 runtime route 决策或个人 `.trellis/.route-prefs.tmp` 时可启动;没有时先进入 `trellis-route` 正常询问 / fallback,写入真实决策后再启动。
|
|
20
|
+
- auto-loop 不默认写 `route_authorization`;只有用户本次明确给出的临时 route 策略,才能通过 `--route-implement` / `--route-check` 传给 runner,且不能当成模型真实执行结果。
|
|
21
|
+
- auto-loop 启动前若 implement 与 check 都缺 route,优先展示 auto-loop 专用的合并选择,不要把 `trellis-route` 的两套完整 fallback 原样贴给用户。仍允许用户回复高级格式 `implement 1, check 1`。
|
|
19
22
|
- 代码提交必须走 `trellis-push` 的 commit-only 语义;不要裸 `git commit` / `git push`。
|
|
20
23
|
|
|
21
24
|
## 启动
|
|
22
25
|
|
|
23
26
|
用户给了任务列表时,按原顺序传入;用户只说当前任务时,用 `task.py current --source` 的当前任务。
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
启动前对当前任务执行 route 准备度检查:
|
|
26
29
|
|
|
27
30
|
```bash
|
|
28
|
-
python3
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target implement
|
|
32
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target check
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
如果两个 target 都返回 `status=miss`,优先用 auto-loop 专用合并选择询问用户,避免把两套 route fallback 列表完整贴出:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
auto-loop 需要你先选执行路线,才能启动。
|
|
39
|
+
|
|
40
|
+
推荐:
|
|
41
|
+
1. 本次全 Inline:implement inline + check-all inline(只影响本次 run)
|
|
42
|
+
2. 本次全 Subagent:implement subagent + check-all subagent(只影响本次 run)
|
|
43
|
+
3. 保存默认全 Inline:写入个人默认,后续自动复用
|
|
44
|
+
4. 保存默认全 Subagent:写入个人默认,后续自动复用
|
|
45
|
+
|
|
46
|
+
高级:也可以回复 `implement 1, check 2` 分别选择。
|
|
33
47
|
```
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
映射规则:
|
|
50
|
+
|
|
51
|
+
- `1` → `--route-implement inline --route-check check-all-inline`
|
|
52
|
+
- `2` → `--route-implement subagent --route-check check-all-subagent`
|
|
53
|
+
- `3` → 先用 `trellis-route` helper 分别写入 `implement=inline`、`check=check-all-inline` 且 `--save-pref`,再启动 runner
|
|
54
|
+
- `4` → 先用 `trellis-route` helper 分别写入 `implement=subagent`、`check=check-all-subagent` 且 `--save-pref`,再启动 runner
|
|
55
|
+
|
|
56
|
+
如果只有一个 target 返回 `status=miss`,再按 `trellis-route` 的对应 target 正常 numbered fallback 询问。不要替用户默认 inline 或 subagent。若用户选择的是本次临时策略,把选择映射为 runner route 参数一起传入,例如 `implement 1, check 1` 对应 `--route-implement inline --route-check check-all-inline`。若用户选择保存默认,则由 `trellis-route` 写入偏好后再启动 runner。
|
|
36
57
|
|
|
37
58
|
```bash
|
|
38
59
|
python3 ./.trellis/scripts/auto_loop.py start \
|
|
39
60
|
--tasks <task> [<task> ...] \
|
|
40
61
|
--profile commit-only \
|
|
41
|
-
--route-implement inline \
|
|
42
|
-
--route-check check-all-inline
|
|
62
|
+
[--route-implement inline|subagent] \
|
|
63
|
+
[--route-check check-all-inline|check-all-subagent]
|
|
43
64
|
```
|
|
44
65
|
|
|
45
|
-
|
|
66
|
+
多任务队列中,当前任务切换到下一个任务且缺少该任务 route 决策时,回到 `trellis-route` 获取该任务真实选择,再继续 `next` / `record`。个人 `.trellis/.route-prefs.tmp` 会由 `trellis-route` 统一复用并写回 runtime。
|
|
46
67
|
|
|
47
68
|
启动后立即运行:
|
|
48
69
|
|
|
@@ -59,7 +80,22 @@ python3 ./.trellis/scripts/auto_loop.py resume
|
|
|
59
80
|
python3 ./.trellis/scripts/auto_loop.py next
|
|
60
81
|
```
|
|
61
82
|
|
|
62
|
-
`resume_capsule`
|
|
83
|
+
`resume` 默认只输出紧凑状态;`resume_capsule` 不再持久写入 runtime JSON,仅在 `resume --verbose` / `status --verbose` 等诊断输出中动态生成。下一步以 `next` 返回的 JSON 为准。
|
|
84
|
+
|
|
85
|
+
## Blocked 后重试
|
|
86
|
+
|
|
87
|
+
如果 `next` 或 `status` 显示 run 内有 blocked 队列项,先根据 blocked reason 补齐条件,然后复用同一个 run:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
python3 ./.trellis/scripts/auto_loop.py retry-blocked \
|
|
91
|
+
[--run-id <run-id>] \
|
|
92
|
+
[--task <task>] \
|
|
93
|
+
[--route-implement inline|subagent] \
|
|
94
|
+
[--route-check check-all-inline|check-all-subagent]
|
|
95
|
+
python3 ./.trellis/scripts/auto_loop.py next
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
常见场景:启动时漏传临时 route,导致 `missing-implement-context` / `missing-check-context`。此时不要 `start --force`,直接用 `retry-blocked --route-implement ... --route-check ...` 重置 blocked 项。
|
|
63
99
|
|
|
64
100
|
## Action 映射
|
|
65
101
|
|
|
@@ -67,12 +103,12 @@ python3 ./.trellis/scripts/auto_loop.py next
|
|
|
67
103
|
| --- | --- | --- |
|
|
68
104
|
| `refresh_brief` | 使用 `trellis-task-brief` 生成并展示 brief | `record --action refresh_brief --result ok` |
|
|
69
105
|
| `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
|
|
106
|
+
| `run_implement` | 进入 Phase 2.1,先用 `trellis-route(target=implement)` 决定 inline/subagent,再实现 | `record --action run_implement --result ok --route-mode <mode> --route-source <source>` |
|
|
107
|
+
| `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>` |
|
|
108
|
+
| `run_fix` | 根据 `last_failure` 修复,复用当前任务 implement route | `record --action run_fix --result ok --route-mode <mode> --route-source <source>` |
|
|
109
|
+
| `run_recheck` | 复用当前任务 check route,重新 check-all | `record --action run_recheck --result ok --route-mode <mode> --route-source <source>` |
|
|
74
110
|
| `run_spec_update` | 有代码/测试证据时用 `trellis-update-spec`;无必要更新也 record ok | `record --action run_spec_update --result ok` |
|
|
75
|
-
| `commit_only` |
|
|
111
|
+
| `commit_only` | 进入 `trellis-push` commit-only 语义:先由 AI 基于 task artifacts 与 git diff 生成提交计划,只提交当前任务可归属文件 | 执行成功后 `record --action commit_only --result ok --commit <hash>` |
|
|
76
112
|
|
|
77
113
|
失败时写回:
|
|
78
114
|
|
|
@@ -97,6 +133,12 @@ python3 ./.trellis/scripts/auto_loop.py record \
|
|
|
97
133
|
|
|
98
134
|
runner 会按 3 轮 fix/recheck 预算决定继续、跳过当前任务或结束队列。
|
|
99
135
|
|
|
136
|
+
`record` 默认只返回当前 item 的 `task`、`item_status`、`current_step`、`commit` 和紧凑 `summary`;只有排查状态漂移时才加 `--verbose` 查看完整 `item`。
|
|
137
|
+
|
|
138
|
+
route action 成功回写时必须带上 `trellis-route` 输出里的真实 `mode` / `source`,例如
|
|
139
|
+
`--route-mode inline --route-source route-prefs` 或
|
|
140
|
+
`--route-mode check-all-subagent --route-source trellis-route`;不要写 auto-loop 默认值。
|
|
141
|
+
|
|
100
142
|
## Commit-Only 预授权
|
|
101
143
|
|
|
102
144
|
auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本地提交”的一次性预授权。只有同时满足这些条件时,`trellis-push` 可以跳过二次聊天确认:
|
|
@@ -104,11 +146,14 @@ auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本
|
|
|
104
146
|
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,且 `outstanding_action.action=commit_only`、`outstanding_action.task` 等于当前活动任务。
|
|
105
147
|
- profile 是 `commit-only`。
|
|
106
148
|
- 模式是 commit-only,不 push、不 merge、不发布、不归档。
|
|
149
|
+
- AI 已基于当前任务 artifacts、`git status`、`git diff` 和必要的文件内容生成提交计划,并能说明每个 planned file 为什么属于当前任务。
|
|
107
150
|
- 提交计划只包含当前任务可归属文件;未识别 dirty 文件保留未提交并写入结果摘要。
|
|
108
151
|
- 执行前复核 git 状态仍与计划一致。
|
|
109
152
|
|
|
110
153
|
如果计划包含未识别 staged 文件、冲突、push/merge/release/archive、真实外部系统或生产数据效果,停止并把当前任务记为 blocked。
|
|
111
154
|
|
|
155
|
+
不要用脚本基于时间差或 dirty baseline 猜测文件归属;语义归属由 AI 负责判断,`trellis-push` 负责展示/复核计划、精确暂存 planned files、执行本地 commit,并把 commit hash 回写 runner。预检不安全时只把当前队列项记为 blocked/skipped,并让 auto-loop 可继续后续任务。
|
|
156
|
+
|
|
112
157
|
## 状态与停止
|
|
113
158
|
|
|
114
159
|
查看:
|
|
@@ -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):
|
|
@@ -12,37 +12,58 @@ description: "启动、恢复和推进 Trellis 自动任务循环。用于用户
|
|
|
12
12
|
- 只有用户明确要求自动跑、auto loop、goal-like、继续自动 run、批量任务队列时才启动或恢复;不要把普通实现请求自动升级为 auto-loop。
|
|
13
13
|
- 每次开始、恢复、压缩后继续时,先运行 runner 的 `resume` 或 `next`,不要凭聊天摘要推断下一步。
|
|
14
14
|
- 每完成一个 action,必须用 `record --action <next 返回的 action>` 精确写回结果;runner 会拒绝缺失或不匹配的 action。写回后立即再调用 `next`,直到 `done`、`blocked` 或需要用户决策。
|
|
15
|
+
- run 进入 `blocked` 后不要用 `start --force` 新建 run 来纠正参数;先补齐缺失 route/context,然后用 `retry-blocked` 在同一个 run 内恢复。
|
|
16
|
+
- runner 默认输出是紧凑 JSON,只包含当前 action、队列计数、简短 blocked/pending/completed 列表和最近少量决策摘要;排障时才给 `status` / `resume` / `next` / `record` / `retry-blocked` 加 `--verbose` 读取完整 item、blocked detail 和 decision data。
|
|
15
17
|
- 默认 profile 是 `commit-only`:自动推进到本地 commit,不 push、不发布、不归档。
|
|
16
18
|
- 多任务只按用户显式给出的任务顺序执行;同一 worktree 不并发。
|
|
17
|
-
- route
|
|
18
|
-
-
|
|
19
|
+
- 启动 runner 前先完成 route 准备度判断:已有当前任务 runtime route 决策或个人 `.trellis/.route-prefs.tmp` 时可启动;没有时先进入 `trellis-route` 正常询问 / fallback,写入真实决策后再启动。
|
|
20
|
+
- auto-loop 不默认写 `route_authorization`;只有用户本次明确给出的临时 route 策略,才能通过 `--route-implement` / `--route-check` 传给 runner,且不能当成模型真实执行结果。
|
|
21
|
+
- auto-loop 启动前若 implement 与 check 都缺 route,优先展示 auto-loop 专用的合并选择,不要把 `trellis-route` 的两套完整 fallback 原样贴给用户。仍允许用户回复高级格式 `implement 1, check 1`。
|
|
19
22
|
- 代码提交必须走 `trellis-push` 的 commit-only 语义;不要裸 `git commit` / `git push`。
|
|
20
23
|
|
|
21
24
|
## 启动
|
|
22
25
|
|
|
23
26
|
用户给了任务列表时,按原顺序传入;用户只说当前任务时,用 `task.py current --source` 的当前任务。
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
启动前对当前任务执行 route 准备度检查:
|
|
26
29
|
|
|
27
30
|
```bash
|
|
28
|
-
python3
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target implement
|
|
32
|
+
python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target check
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
如果两个 target 都返回 `status=miss`,优先用 auto-loop 专用合并选择询问用户,避免把两套 route fallback 列表完整贴出:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
auto-loop 需要你先选执行路线,才能启动。
|
|
39
|
+
|
|
40
|
+
推荐:
|
|
41
|
+
1. 本次全 Inline:implement inline + check-all inline(只影响本次 run)
|
|
42
|
+
2. 本次全 Subagent:implement subagent + check-all subagent(只影响本次 run)
|
|
43
|
+
3. 保存默认全 Inline:写入个人默认,后续自动复用
|
|
44
|
+
4. 保存默认全 Subagent:写入个人默认,后续自动复用
|
|
45
|
+
|
|
46
|
+
高级:也可以回复 `implement 1, check 2` 分别选择。
|
|
33
47
|
```
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
映射规则:
|
|
50
|
+
|
|
51
|
+
- `1` → `--route-implement inline --route-check check-all-inline`
|
|
52
|
+
- `2` → `--route-implement subagent --route-check check-all-subagent`
|
|
53
|
+
- `3` → 先用 `trellis-route` helper 分别写入 `implement=inline`、`check=check-all-inline` 且 `--save-pref`,再启动 runner
|
|
54
|
+
- `4` → 先用 `trellis-route` helper 分别写入 `implement=subagent`、`check=check-all-subagent` 且 `--save-pref`,再启动 runner
|
|
55
|
+
|
|
56
|
+
如果只有一个 target 返回 `status=miss`,再按 `trellis-route` 的对应 target 正常 numbered fallback 询问。不要替用户默认 inline 或 subagent。若用户选择的是本次临时策略,把选择映射为 runner route 参数一起传入,例如 `implement 1, check 1` 对应 `--route-implement inline --route-check check-all-inline`。若用户选择保存默认,则由 `trellis-route` 写入偏好后再启动 runner。
|
|
36
57
|
|
|
37
58
|
```bash
|
|
38
59
|
python3 ./.trellis/scripts/auto_loop.py start \
|
|
39
60
|
--tasks <task> [<task> ...] \
|
|
40
61
|
--profile commit-only \
|
|
41
|
-
--route-implement inline \
|
|
42
|
-
--route-check check-all-inline
|
|
62
|
+
[--route-implement inline|subagent] \
|
|
63
|
+
[--route-check check-all-inline|check-all-subagent]
|
|
43
64
|
```
|
|
44
65
|
|
|
45
|
-
|
|
66
|
+
多任务队列中,当前任务切换到下一个任务且缺少该任务 route 决策时,回到 `trellis-route` 获取该任务真实选择,再继续 `next` / `record`。个人 `.trellis/.route-prefs.tmp` 会由 `trellis-route` 统一复用并写回 runtime。
|
|
46
67
|
|
|
47
68
|
启动后立即运行:
|
|
48
69
|
|
|
@@ -59,7 +80,22 @@ python3 ./.trellis/scripts/auto_loop.py resume
|
|
|
59
80
|
python3 ./.trellis/scripts/auto_loop.py next
|
|
60
81
|
```
|
|
61
82
|
|
|
62
|
-
`resume_capsule`
|
|
83
|
+
`resume` 默认只输出紧凑状态;`resume_capsule` 不再持久写入 runtime JSON,仅在 `resume --verbose` / `status --verbose` 等诊断输出中动态生成。下一步以 `next` 返回的 JSON 为准。
|
|
84
|
+
|
|
85
|
+
## Blocked 后重试
|
|
86
|
+
|
|
87
|
+
如果 `next` 或 `status` 显示 run 内有 blocked 队列项,先根据 blocked reason 补齐条件,然后复用同一个 run:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
python3 ./.trellis/scripts/auto_loop.py retry-blocked \
|
|
91
|
+
[--run-id <run-id>] \
|
|
92
|
+
[--task <task>] \
|
|
93
|
+
[--route-implement inline|subagent] \
|
|
94
|
+
[--route-check check-all-inline|check-all-subagent]
|
|
95
|
+
python3 ./.trellis/scripts/auto_loop.py next
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
常见场景:启动时漏传临时 route,导致 `missing-implement-context` / `missing-check-context`。此时不要 `start --force`,直接用 `retry-blocked --route-implement ... --route-check ...` 重置 blocked 项。
|
|
63
99
|
|
|
64
100
|
## Action 映射
|
|
65
101
|
|
|
@@ -67,12 +103,12 @@ python3 ./.trellis/scripts/auto_loop.py next
|
|
|
67
103
|
| --- | --- | --- |
|
|
68
104
|
| `refresh_brief` | 使用 `trellis-task-brief` 生成并展示 brief | `record --action refresh_brief --result ok` |
|
|
69
105
|
| `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
|
|
106
|
+
| `run_implement` | 进入 Phase 2.1,先用 `trellis-route(target=implement)` 决定 inline/subagent,再实现 | `record --action run_implement --result ok --route-mode <mode> --route-source <source>` |
|
|
107
|
+
| `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>` |
|
|
108
|
+
| `run_fix` | 根据 `last_failure` 修复,复用当前任务 implement route | `record --action run_fix --result ok --route-mode <mode> --route-source <source>` |
|
|
109
|
+
| `run_recheck` | 复用当前任务 check route,重新 check-all | `record --action run_recheck --result ok --route-mode <mode> --route-source <source>` |
|
|
74
110
|
| `run_spec_update` | 有代码/测试证据时用 `trellis-update-spec`;无必要更新也 record ok | `record --action run_spec_update --result ok` |
|
|
75
|
-
| `commit_only` |
|
|
111
|
+
| `commit_only` | 进入 `trellis-push` commit-only 语义:先由 AI 基于 task artifacts 与 git diff 生成提交计划,只提交当前任务可归属文件 | 执行成功后 `record --action commit_only --result ok --commit <hash>` |
|
|
76
112
|
|
|
77
113
|
失败时写回:
|
|
78
114
|
|
|
@@ -97,6 +133,12 @@ python3 ./.trellis/scripts/auto_loop.py record \
|
|
|
97
133
|
|
|
98
134
|
runner 会按 3 轮 fix/recheck 预算决定继续、跳过当前任务或结束队列。
|
|
99
135
|
|
|
136
|
+
`record` 默认只返回当前 item 的 `task`、`item_status`、`current_step`、`commit` 和紧凑 `summary`;只有排查状态漂移时才加 `--verbose` 查看完整 `item`。
|
|
137
|
+
|
|
138
|
+
route action 成功回写时必须带上 `trellis-route` 输出里的真实 `mode` / `source`,例如
|
|
139
|
+
`--route-mode inline --route-source route-prefs` 或
|
|
140
|
+
`--route-mode check-all-subagent --route-source trellis-route`;不要写 auto-loop 默认值。
|
|
141
|
+
|
|
100
142
|
## Commit-Only 预授权
|
|
101
143
|
|
|
102
144
|
auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本地提交”的一次性预授权。只有同时满足这些条件时,`trellis-push` 可以跳过二次聊天确认:
|
|
@@ -104,11 +146,14 @@ auto-loop 的 `commit-only` profile 是用户对“当前 run 内任务相关本
|
|
|
104
146
|
- `.trellis/scripts/auto_loop.py status` 显示当前 `run_status=running`,且 `outstanding_action.action=commit_only`、`outstanding_action.task` 等于当前活动任务。
|
|
105
147
|
- profile 是 `commit-only`。
|
|
106
148
|
- 模式是 commit-only,不 push、不 merge、不发布、不归档。
|
|
149
|
+
- AI 已基于当前任务 artifacts、`git status`、`git diff` 和必要的文件内容生成提交计划,并能说明每个 planned file 为什么属于当前任务。
|
|
107
150
|
- 提交计划只包含当前任务可归属文件;未识别 dirty 文件保留未提交并写入结果摘要。
|
|
108
151
|
- 执行前复核 git 状态仍与计划一致。
|
|
109
152
|
|
|
110
153
|
如果计划包含未识别 staged 文件、冲突、push/merge/release/archive、真实外部系统或生产数据效果,停止并把当前任务记为 blocked。
|
|
111
154
|
|
|
155
|
+
不要用脚本基于时间差或 dirty baseline 猜测文件归属;语义归属由 AI 负责判断,`trellis-push` 负责展示/复核计划、精确暂存 planned files、执行本地 commit,并把 commit hash 回写 runner。预检不安全时只把当前队列项记为 blocked/skipped,并让 auto-loop 可继续后续任务。
|
|
156
|
+
|
|
112
157
|
## 状态与停止
|
|
113
158
|
|
|
114
159
|
查看:
|
|
@@ -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 the strongest 1-2 matched SOP/spec files 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 the strongest 1-2 matched SOP/spec files 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 the strongest 1-2 matched SOP/spec files 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 the strongest 1-2 matched SOP/spec files 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 the strongest 1-2 matched SOP/spec files 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,27 @@
|
|
|
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 the strongest 1-2 matched SOP/spec files before acting. Continue to lower-ranked
|
|
27
|
+
matches only when their path, heading, or trigger reason is clearly relevant; if
|
|
28
|
+
nothing matches, continue normally.
|
|
29
|
+
|
|
13
30
|
#### Task Brief Handoff
|
|
14
31
|
|
|
15
32
|
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.
|