跳转到主要内容

定制 Workflow

.trellis/workflow.md 是 Trellis 开发流程的单一事实源(single source of truth)——Phase 定义、skill 路由、每轮面包屑、task.py 命令参考都在这一个文件里。Fork 工作流 = 改一个 markdown 文件,不用动 Python、不用改 hook、不用重发包。 0.5 之前,工作流行为分散在三处:hook Python 脚本、configurator TypeScript、命令 markdown;想 fork 一份”自己的工作流”得同时改三处才能自洽。0.5 把这三处收敛到 workflow.md 一个文件。

workflow.md 控制了哪些东西

workflow.md 里的段落谁来读效果
## Phase Index + ## Phase 1/2/3AI 在会话开始时读(通过 SessionStart hook)定义三阶段流程和每个阶段的 step 级 how-to
### Skill RoutingAI 在会话开始时读把用户意图映射到要加载的 skill(例如”想做新功能”→ trellis-brainstorm
### DO NOT skip skillsAI 在会话开始时读列出 AI 想跳过 skill 时常见的借口以及为什么不对
## Workflow State Breadcrumbsinject-workflow-state.py 在每次 UserPromptSubmit 触发每轮用 <workflow-state>…</workflow-state> 注入一段面包屑,内容按当前任务 status 变
### Task System(task.py 命令表)AI 在会话开始时读16 个 task.py 子命令按用途分组的参考
所有注入路径都在运行时读 workflow.md——改完不用重 build。

改每轮面包屑

每轮注入的 <workflow-state> 块是根据当前任务 status 字段提醒 AI 下一步该做什么。改内容不用碰 hook 脚本。
## Workflow State Breadcrumbs

[workflow-state:no_task]
No active task. If the user describes multi-step work, load trellis-brainstorm skill…
[/workflow-state:no_task]

[workflow-state:planning]
Complete prd.md via trellis-brainstorm skill; then run task.py start.
[/workflow-state:planning]

[workflow-state:in_progress]
Flow: implement → check → update-spec → finish
Check conversation history + git status to determine current step; do NOT skip check.
[/workflow-state:in_progress]

[workflow-state:completed]
User commits changes; then run task.py archive.
[/workflow-state:completed]
规则:
  • 标签 STATUS 对应 task.json.status。默认:planning / in_progress / completed,没活跃任务时走 no_task
  • 标签名短横线和下划线都支持(blocked / in-review / needs_qa 等)。
  • 某个状态没有匹配的标签块时,hook 走内置兜底——用不到的块可以删掉。
  • 每个块保持简短(≈200 字节)。这是每轮都注入的东西,写长了 AI 每条消息都要付注意力代价。

加一个自定义状态

想要一个 blocked 状态,提醒 AI 不要硬猜而是先上报?
[workflow-state:blocked]
Task is blocked waiting on external input. Don't start new implementation —
surface the blocker to the user or spawn `trellis-research` if more investigation helps.
[/workflow-state:blocked]
然后直接改 task.json 把状态设成 blocked
# 改成自定义状态
jq '.status = "blocked"' "$TASK_DIR/task.json" > "$TASK_DIR/task.json.tmp" && mv "$TASK_DIR/task.json.tmp" "$TASK_DIR/task.json"
从下一条消息起,AI 每轮看到 blocked 面包屑。改回 in_progress 就恢复正常流。 task.py 的子命令只做默认状态流转(startin_progressarchivecompleted)。自定义状态在 task.json.status 里就是普通字符串——面包屑系统不要求预注册,task.py list --status <name> 也能按任意字符串过滤。

改 skill 路由表

### Skill Routing 下面的表是 AI 决定要不要加载 auto-trigger skill 时查的。
| User intent                                  | Skill                |
|----------------------------------------------|----------------------|
| Wants a new feature / requirement unclear    | trellis-brainstorm   |
| About to write code / start implementing     | trellis-before-dev   |
| Finished writing / want to verify            | trellis-check        |
| Stuck / fixed same bug several times         | trellis-break-loop   |
| Spec needs update                            | trellis-update-spec  |
自己写了个 skill(见第 12 章:定制 Skill),在这里加一行就够:
| 写代码前想先要一份测试计划                   | trellis-test-plan    |
不用改代码——下一个会话,AI 读到更新后的表就会按新路由选 skill。

加 / 改 Phase

Phase 段落都是普通 markdown。你可以:
  • 加一个 Phase 4: Review —— 定义 4.1、4.2 … step 和 how-to;再从面包屑引用([workflow-state:in_review])。
  • 把 Plan 拆成 A/B 两条分支 —— 把 step 编号改成 1A.1 / 1B.1;AI 按正文内容走。
  • 压缩 Finish —— 删你不关心的 step(比如去掉 3.2 debug retrospective)。
改完保持 Phase Index 和详细 Phase 段落同步——SessionStart 把两者都内联进去,AI 得看到一致内容。
get_context.py --mode phase --step X.Y 解析 ## Phase X 标题 + #### X.Y step 标题来提取正文。改名或改结构时,确保 step 锚点仍可解析(标题层级有语义)。

哪些东西不要

有几处约定被脚本依赖,改了会坏:
不要改原因
标签格式 [workflow-state:STATUS]…[/workflow-state:STATUS]inject-workflow-state.py 按字面解析
Phase / step 的标题层级(## Phase X + #### X.Yget_context.py --mode phase --step X.Y 依赖这个
任务生命周期里的 task.py 子命令名必须和实际 CLI 一致;文档里改名不会改脚本
其他——措辞、顺序、加段、重写 how-to 正文——都可以随便改。

改动什么时候生效

改动AI 什么时候看到
面包屑文本下一条用户消息(每次 UserPromptSubmit 重读)
Phase / step 正文下一个会话(SessionStart 重读)
Skill 路由表下一个会话
Fork 不用重发包。把改过的 workflow.md commit 进仓库,团队下个会话就自动拿到新版。