> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trytrellis.app/llms.txt
> Use this file to discover all available pages before exploring further.

# v0.5.0-beta.18

> 2026-04-29

beta.18 重新设计了 workflow Phase 3：新增 `Phase 3.4 Commit changes` 步骤，让 AI 按本次 session 改动批量起草 commit；`/trellis:finish-work` 回归 archive + journal 语义，工作区还有未提交代码改动时拒绝执行。同时修复了子任务归档导致父任务进度回退的 bug、`trellis update` 期间 `AGENTS.md` 哈希追踪的问题，以及 OpenCode 在 Windows 下的 PowerShell context 注入。

## Enhancements

### Phase 3.4 Commit changes

`workflow.md` Phase 3 新增必选步骤 `3.4 Commit changes`，由 AI 主导 commit 节奏，不再丢给用户手动处理。

| Step | AI 的具体动作                                                              |
| ---- | --------------------------------------------------------------------- |
| 1    | 跑 `git status --porcelain` 快照所有 dirty path                            |
| 2    | 跑 `git log --oneline -5` 学习 repo 的 commit message 风格（前缀 / 语言 / 长度）    |
| 3    | 把 dirty 文件分成 `AI 本会话编辑过` 和 `未识别` 两组                                   |
| 4    | 起草多 commit plan，每批一个语义内聚的改动                                           |
| 5    | 一次性展示 plan 给用户 confirm                                                |
| 6    | 用户确认后：每批跑 `git add` + `git commit`，不允许 `--amend`，不允许 `git push`       |
| 7    | 用户拒绝（"不行" / "我自己来" / "manual" / 任何反对）：退出 commit 编排，不做第二次 plan，无需 flag |

原 `3.4` 的 Wrap-up reminder 顺移到 `3.5`。`[workflow-state:completed]` breadcrumb（以及 `inject-workflow-state.py` / `inject-workflow-state.js` 的四份 hook fallback）现在统一指向 `/trellis:finish-work`，不再走老的 `task.py finish` + `task.py archive` 提示。

### `/trellis:finish-work` 回归 survey + archive + journal

skill 删掉了原本的 "Remind user to commit" 步骤，加了一步 survey 帮你发现遗忘的已完成任务。新流程是：

| Step | 动作                                                                                                                                   |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------ |
| 1    | `get_context.py --mode record` 输出 active tasks、git status 和 recent commits。如果除了当前 task 之外还有其它看起来已完成的 task，一次性问用户："这 N 个一并归档吗？\[y/N]" |
| 2    | 跑 `git status --porcelain`，排除 `.trellis/workspace/` 和 `.trellis/tasks/`（这两个路径由脚本 auto-commit 管理）。其它路径有 dirty 文件就拒绝执行。                |
| 3    | 对当前 active task 跑 `task.py archive <task>`（一定归档）+ Step 1 用户确认的其它 task。每条产生一个 `chore(task): archive ...` commit                       |
| 4    | 跑 `add_session.py --commit <hashes>` 写 session journal（产生 `chore: record journal` commit）。hash 取自 Step 1 的 `Recent commits` 输出       |

最终 git log 顺序固定为 `<3.4 阶段的 work commits>` → `chore(task): archive ...`（可能多条）→ `chore: record journal`，bookkeeping commit 永远在 work commit 之后，不再交错。

common skill 模板用 `{{CMD_REF:finish-work}}` 占位符，每个平台按自己的 `cmdRefPrefix` 解析：Claude Code / OpenCode 是 `/trellis:finish-work`，Codex 是 `$finish-work`，Cursor 是 `/trellis-finish-work`。

## Bug Fixes

### 子任务归档不再让父任务进度倒退

`task.py list` 之前会在子任务被归档后从父任务的 `[x/y done]` 计数里把它丢掉。

| 场景              | beta.18 之前   | beta.18      |
| --------------- | ------------ | ------------ |
| 6 个子任务，1 个完成并归档 | `[0/5 done]` | `[1/6 done]` |
| 6 个子任务，2 个完成并归档 | `[0/4 done]` | `[2/6 done]` |

`cmd_archive` 不再从父任务的 `children` 列表里移除归档过的子任务，`children_progress` 把"不在活跃状态表里的 child"视为已完成（`cmd_archive` 在移动目录前总会把状态改成 `completed`）。这个 invariant 已写入 `.trellis/spec/cli/backend/script-conventions.md` 的 "Parent-child invariant" 一节。

### `trellis update` 期间 `AGENTS.md` 哈希追踪

beta.18 之前的项目写过 `AGENTS.md` 但没记录模板哈希，所以 update 时会被当成 "modified by you" 冲突。beta.18 引入：

| 机制                                                  | 行为                                                                        |
| --------------------------------------------------- | ------------------------------------------------------------------------- |
| `<!-- TRELLIS:START -->` block                      | 标记 `AGENTS.md` 内的 Trellis 管理区域；`update` 只替换这个 block，外面的用户内容一律保留           |
| `LEGACY_UNTRACKED_AGENTS_MD_BLOCK_HASHES` allowlist | 收录 beta.18 之前 pristine 状态下的 block hash（如 `c1f511b1...`），匹配中即静默通过，老项目不会被追问 |
| Hash tracking                                       | `template-hash.ts` 此后会记录新模板的哈希，后续 update 走正常分类流程                          |

block 之外的用户自定义内容一律保留。

### OpenCode 在 Windows 下的 PowerShell context 注入

`inject-subagent-context.js` 现在按 `host.platform` 选择正确的 shell 语法：

| Platform | 注入的前缀                                          |
| -------- | ---------------------------------------------- |
| `win32`  | `$env:TRELLIS_CONTEXT_ID = '<key>'; <command>` |
| 其它       | `export TRELLIS_CONTEXT_ID='<key>'; <command>` |

显式赋值的去重检测器同时识别 POSIX 形式（`TRELLIS_CONTEXT_ID=...`、`export TRELLIS_CONTEXT_ID=...`）和 PowerShell 形式（`$env:TRELLIS_CONTEXT_ID = ...`），用户手动加过前缀的命令不会被二次包装。

## Internal

### Vitest 测试隔离：清掉 host shell 的 session env

`packages/cli/test/setup.ts` 通过 `vitest.config.ts` 的 `setupFiles` 注册，在 vitest 进程启动时 `delete process.env.TRELLIS_CONTEXT_ID` 和 `process.env.OPENCODE_RUN_ID`，这样 OpenCode resolver 的测试就不会被 Claude / OpenCode 宿主 session 的 env 漏进来 hijack 掉 platform-input 推导出的 `contextKey`。这个模式已写入 `.trellis/spec/cli/unit-test/conventions.md` 的 "Test Isolation" 一节。

### Spec 更新

| Spec 文件                                           | 新增内容                                                                    |
| ------------------------------------------------- | ----------------------------------------------------------------------- |
| `.trellis/spec/cli/backend/script-conventions.md` | 父子任务 `children` 列表 invariant —— 历史列表，归档时不剔除，`children_progress` 把缺失视为完成 |
| `.trellis/spec/cli/unit-test/conventions.md`      | Test Isolation 模式 —— 在 vitest setup 里清掉 host shell 的 session env vars   |

## Upgrade

存量项目：

```bash theme={null}
trellis update
```

本次 beta 不需要加 `--migrate` flag。
