flower-trellis 0.5.5 → 0.5.6-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.
Files changed (75) hide show
  1. package/README.md +8 -0
  2. package/enhancements/0.6/.agents/skills/trellis-auto-loop/SKILL.md +11 -7
  3. package/enhancements/0.6/.agents/skills/trellis-check-all/SKILL.md +3 -2
  4. package/enhancements/0.6/.agents/skills/trellis-check-all/references/depth-routing.md +10 -2
  5. package/enhancements/0.6/.agents/skills/trellis-check-all/references/full-profile.md +2 -0
  6. package/enhancements/0.6/.agents/skills/trellis-check-all/references/light-profile.md +2 -0
  7. package/enhancements/0.6/.agents/skills/trellis-check-all/references/reporting-and-disposition.md +4 -2
  8. package/enhancements/0.6/.agents/skills/trellis-push/SKILL.md +38 -14
  9. package/enhancements/0.6/.agents/skills/trellis-route/SKILL.md +36 -9
  10. package/enhancements/0.6/.agents/skills/trellis-route/scripts/route_state.py +93 -1
  11. package/enhancements/0.6/.claude/skills/trellis-auto-loop/SKILL.md +11 -7
  12. package/enhancements/0.6/.claude/skills/trellis-check-all/SKILL.md +3 -2
  13. package/enhancements/0.6/.claude/skills/trellis-check-all/references/depth-routing.md +10 -2
  14. package/enhancements/0.6/.claude/skills/trellis-check-all/references/full-profile.md +2 -0
  15. package/enhancements/0.6/.claude/skills/trellis-check-all/references/light-profile.md +2 -0
  16. package/enhancements/0.6/.claude/skills/trellis-check-all/references/reporting-and-disposition.md +4 -2
  17. package/enhancements/0.6/.claude/skills/trellis-push/SKILL.md +38 -14
  18. package/enhancements/0.6/.claude/skills/trellis-route/SKILL.md +36 -9
  19. package/enhancements/0.6/.claude/skills/trellis-route/scripts/route_state.py +93 -1
  20. package/enhancements/0.6/overrides/bundles/intent-routing.json +3 -1
  21. package/enhancements/0.6/overrides/bundles/untracked-execution.json +16 -0
  22. package/enhancements/0.6/overrides/conflicts.json +4 -2
  23. package/enhancements/0.6/overrides/patches/agents/untracked-context/codex-content.md +2 -0
  24. package/enhancements/0.6/overrides/patches/agents/untracked-context/codex-selector.md +1 -0
  25. package/enhancements/0.6/overrides/patches/agents/untracked-context/kiro-content.txt +1 -0
  26. package/enhancements/0.6/overrides/patches/agents/untracked-context/kiro-selector.txt +1 -0
  27. package/enhancements/0.6/overrides/patches/agents/untracked-context/markdown-check-selector.md +1 -0
  28. package/enhancements/0.6/overrides/patches/agents/untracked-context/markdown-content.md +8 -0
  29. package/enhancements/0.6/overrides/patches/agents/untracked-context/markdown-implement-selector.md +1 -0
  30. package/enhancements/0.6/overrides/patches/agents/untracked-context/patch.json +83 -0
  31. package/enhancements/0.6/overrides/patches/hooks/inject-workflow-state/shared-runtime/baseline-flower-pre-untracked.py +443 -0
  32. package/enhancements/0.6/overrides/patches/hooks/inject-workflow-state/shared-runtime/content.py +53 -7
  33. package/enhancements/0.6/overrides/patches/hooks/inject-workflow-state/shared-runtime/patch.json +6 -1
  34. package/enhancements/0.6/overrides/patches/hooks/session-start/pre-check-hold/claude-content.py +13 -0
  35. package/enhancements/0.6/overrides/patches/hooks/session-start/pre-check-hold/codex-content.py +13 -0
  36. package/enhancements/0.6/overrides/patches/skills/trellis-meta/managed-workflow-owners/owner-routing-content.md +2 -0
  37. package/enhancements/0.6/overrides/patches/skills/trellis-meta/managed-workflow-owners/workflow-change-map-content.md +1 -0
  38. package/enhancements/0.6/overrides/patches/skills/trellis-start/no-task-routing/content.md +1 -1
  39. package/enhancements/0.6/overrides/patches/skills/trellis-update-spec/autonomous-evaluation/content.md +8 -6
  40. package/enhancements/0.6/overrides/patches/workflow/hub/content.md +3 -1
  41. package/enhancements/0.6/overrides/patches/workflow/intent-routing/request-triage/content.md +3 -0
  42. package/enhancements/0.6/overrides/patches/workflow/phase-ownership/phase-2-check-content.md +3 -1
  43. package/enhancements/0.6/overrides/patches/workflow/phase-ownership/phase-2-implement-content.md +5 -1
  44. package/enhancements/0.6/overrides/patches/workflow/phase-ownership/phase-3-commit-content.md +2 -0
  45. package/enhancements/0.6/overrides/patches/workflow/phase-ownership/phase-3-update-spec-content.md +2 -0
  46. package/enhancements/0.6/overrides/patches/workflow/runtime-contract-reference/runtime-reference-content.md +1 -1
  47. package/enhancements/0.6/overrides/patches/workflow/runtime-contract-reference/state-contract-comment-content.md +2 -1
  48. package/enhancements/0.6/overrides/patches/workflow/state-no-task/content.md +1 -1
  49. package/enhancements/0.6/overrides/patches/workflow/state-untracked/content.md +8 -0
  50. package/enhancements/0.6/overrides/patches/workflow/state-untracked/patch.json +13 -0
  51. package/enhancements/0.6/overrides/patches/workflow/state-untracked/selector.md +1 -0
  52. package/enhancements/0.6/scripts/auto_loop.py +317 -49
  53. package/enhancements/0.6/scripts/git_evidence.py +343 -0
  54. package/enhancements/0.6/scripts/pre_check_state.py +108 -30
  55. package/enhancements/0.6/scripts/task_intent.py +190 -55
  56. package/enhancements/0.6/scripts/untracked_flow.py +800 -0
  57. package/enhancements/MANIFEST.json +20 -3
  58. package/enhancements/common/.common/.claude/skills/aliyun-sls-query/SKILL.md +164 -0
  59. package/enhancements/common/.common/.claude/skills/aliyun-sls-query/assets/env.example +6 -0
  60. package/enhancements/common/.common/.claude/skills/aliyun-sls-query/scripts/sls_get_logs.py +259 -0
  61. package/enhancements/common/.common/.codex/skills/aliyun-sls-query/SKILL.md +164 -0
  62. package/enhancements/common/.common/.codex/skills/aliyun-sls-query/assets/env.example +6 -0
  63. package/enhancements/common/.common/.codex/skills/aliyun-sls-query/scripts/sls_get_logs.py +259 -0
  64. package/package.json +3 -3
  65. package/src/builtin-plugins/skill-garden/content-adapter.js +12 -0
  66. package/src/cli.js +4 -0
  67. package/src/commands/init.js +3 -0
  68. package/src/commands/self-check.js +5 -1
  69. package/src/commands/telemetry.js +56 -0
  70. package/src/commands/update.js +5 -0
  71. package/src/lib/copy-scripts.js +35 -0
  72. package/src/lib/patch-engine.js +15 -0
  73. package/src/lib/self-check.js +8 -2
  74. package/src/lib/telemetry.js +322 -0
  75. package/src/lib/update-check.js +11 -2
package/README.md CHANGED
@@ -64,6 +64,9 @@ flower-trellis self-update --target . --yes
64
64
  # 管理启动更新检查策略
65
65
  flower-trellis update-check get --target .
66
66
 
67
+ # 查看或修改匿名安装遥测开关
68
+ flower-trellis telemetry status
69
+
67
70
  # 卸载:移除 Trellis 本体并清理强化包残留
68
71
  flower-trellis uninstall
69
72
 
@@ -73,6 +76,8 @@ flower-trellis -v
73
76
 
74
77
  > 已全局安装时可直接写 `flower-trellis`、`ftl` 或 `ft`(三者等价);未安装则在命令前加 `npx`。
75
78
 
79
+ 为统计安装活跃度和版本分布,CLI 默认在远程版本检查及 `init` / `update` 成功后上报随机设备 ID、Flower/Trellis 版本、项目 `.trellis/.developer` 名称和运行平台;不采集 MAC、主机名、系统用户名、项目路径或仓库地址。可用 `flower-trellis telemetry disable` 持久停用,或用 `FLOWER_NO_TELEMETRY=1` 临时停用。
80
+
76
81
  ### 命令
77
82
 
78
83
  | 命令 | 说明 |
@@ -82,6 +87,7 @@ flower-trellis -v
82
87
  | `self-check` | 输出启动更新检查 JSON,供 Codex / Claude Code hook 和 AI 自动化读取 |
83
88
  | `self-update` | 受控升级 flower-trellis 并对目标项目执行完整 `flower-trellis update` 重叠加 |
84
89
  | `update-check` | 管理 `.trellis/.flower-manifest.json` 内的启动更新检查策略 |
90
+ | `telemetry` | 查询、启用或停用用户级匿名安装遥测 |
85
91
  | `plugin` | 管理 Flower Plugin、Marketplace 来源、GitLab 授权和作者校验 |
86
92
  | `uninstall` | 移除 Trellis 本体并清理强化包残留(支持 `-y` / `--dry-run`) |
87
93
  | `<其它命令>` | 原样透传给 Trellis,覆盖其现有及未来子命令 |
@@ -113,6 +119,8 @@ flower-trellis plugin
113
119
 
114
120
  交互管理器采用 `发现 / 已安装 / 来源 / 问题` 四个页签。Trellis 项目的 `发现` 页会展示 `flower/skill-garden` 内置入口,按 Enter 直接管理工作流强化与可选通用技能;原 `flower-trellis skill` 命令继续保留为高级兼容入口。`发现` 同时合并全部已启用来源的 Plugin,并保留来源标签和即时搜索;未登录 GitLab 来源会直接进入 Device Flow,GitHub 公共来源无需登录。`来源` 页的“新增来源”可选择 GitHub 公共仓库或 GitLab Marketplace;GitHub 会先在临时缓存中下载固定快照、检测格式、展示可导入与忽略组件,确认后才保存。ref 留空时使用仓库默认分支;出现多个格式入口时会要求选择,公开 GitHub 跨仓 Marketplace 条目和 `plugins/*` 多 Plugin 仓库也可识别。
115
121
 
122
+ 可选通用技能包含 `aliyun-sls-query`,可为 Codex / Claude 项目安装零第三方依赖的阿里云 SLS 查询脚本与排障知识;默认不安装,也不会复制用户私有 AK/SK 配置。
123
+
116
124
  安装、更新和卸载都会先展示 dry-run、依赖、capability 和目标文件变化,确认后才写入项目。Plugin 作者使用的 `plugin init`、`plugin validate` 继续保留在高级命令中,不占用普通用户的管理器首页。
117
125
 
118
126
  独立的 `plugin add` 只建立最小 Plugin Runtime,安装目标 Plugin 及其显式依赖,不会隐式安装 `skill-garden`,因此交互管理器也可以在没有 `.trellis/` 的普通项目中使用。
@@ -16,7 +16,7 @@ description: "启动、恢复和推进 Trellis 自动任务循环。用于用户
16
16
  - `record` 返回 `status=retryable` 时保留的是同一个 outstanding Check action:不得运行 `next`,必须先按返回指令消解漂移并重录。
17
17
  - 本地提交是自动终点。不得 push、merge、release、deploy、finish-work 或 archive;queue item 完成后 Trellis task 仍保持 `in_progress`。
18
18
  - 任务顺序只决定稳定调度顺序,不隐含依赖。依赖必须通过 `--depends-on dependent=dependency` 明确传入或由 planning artifacts 明确声明。
19
- - 任务级失败只阻塞自身及显式依赖项;独立任务继续。fix/recheck 与 planning repair 各最多 3 轮,队列结束后不自动执行第二遍恢复扫描。
19
+ - 任务级失败只阻塞自身及显式依赖项;独立任务继续。fix/recheck、planning repair 与安全的 commit-only repair 各最多 3 轮,队列结束后不自动执行第二遍恢复扫描。
20
20
  - schema 1 runtime 继续按 runner 返回的旧 action 恢复,包括 outstanding `confirm_brief`;不要把旧 run 改写成 schema 2。
21
21
 
22
22
  启动或恢复前静默清除交互式 pre-check hold;miss、task mismatch 或损坏诊断不阻断 runner:
@@ -105,7 +105,7 @@ python3 ./.trellis/scripts/auto_loop.py decide \
105
105
  | `run_fix` | 根据 `last_failure` 修复并复用 implement route | `record --action run_fix --result ok --route-mode <mode> --route-source <source>` |
106
106
  | `run_recheck` | 复用 check route,且不得低于 `minimum_check_depth` | 同 `run_check_all`,action 改为 `run_recheck` |
107
107
  | `run_spec_update` | 执行 `trellis-update-spec` | `no-op|written` 用 ok;`needs-review` 用 blocked + `spec-needs-review` |
108
- | `commit_only` | 复用 `trellis-push` 内部精确本地提交能力,不 push | `record --action commit_only --result ok --commit <hash> --files <exact...> --commit-message "..."` |
108
+ | `commit_only` | 复用 `trellis-push` 内部多仓精确本地提交能力,不 push | `record --action commit_only --result ok --commit <primary-or-last-hash> [--repo-commit <repository>::<hash> ...] --files <exact...> --commit-message "..."` |
109
109
 
110
110
  失败或越权时必须回写,runner 决定重试、blocked 或继续队列:
111
111
 
@@ -113,6 +113,7 @@ python3 ./.trellis/scripts/auto_loop.py decide \
113
113
  python3 ./.trellis/scripts/auto_loop.py record \
114
114
  --action <action> --result failed|blocked \
115
115
  --failure-type <type> --summary "<摘要>" \
116
+ [--repo-commit <repository>::<hash> ...] \
116
117
  [--files <repository>::<path> ...]
117
118
  python3 ./.trellis/scripts/auto_loop.py next
118
119
  ```
@@ -128,17 +129,20 @@ Check-All 自动修复当前任务 `implement.md` 或 `brief.md` 时,每个实
128
129
  3. 若是合法 `implement.md` / `brief.md` DOC 修复,补齐精确 `--doc-remediation-file` 后重录。
129
130
  4. 若无法安全归因,使用原 action、`--result blocked --failure-type artifact-drift` 重录并停止。
130
131
 
131
- 同一 Check action 最多允许 3 次 retryable 自纠,第 4 次进入 terminal blocked。实现、spec update、commit-only 等其它 action 的 artifact drift 不使用该预算。
132
+ 同一 Check action 最多允许 3 次 retryable 自纠,第 4 次进入 terminal blocked。实现、spec update、commit-only 等其它 action 的 artifact drift 不使用该预算;commit-only 只有下方明确的 `commit-repairable` 本地失败可以使用独立三轮预算。
132
133
 
133
134
  ## Commit-Only
134
135
 
135
136
  收到 `commit_only` 后:
136
137
 
137
138
  1. 用 `status` 确认 active run、profile、outstanding action 和 task 一致。
138
- 2. 读取任务 artifacts、Git status/diff,生成 exact files、message 和归属理由。
139
- 3. staged 必须为空;不得包含冲突、未完成集成、runtime、route prefs、其它任务目录或 protected-retained。
140
- 4. 使用 `trellis-push` 内部 commit-only 提交 exact files。不得裸 `git add .`、`git add -A`、push 或按时间差猜归属。
141
- 5. 用提交 hash 和 exact files record,然后立即 next。
139
+ 2. 调用 `trellis-push` 内部 `commit-only`,由它根据任务 artifacts、项目 SOP/spec、受版本控制脚本和可验证 Git/submodule 关系,从当前真实 Git 状态生成有序 `commit -> generate -> commit` 链。不得仅因多个仓库、submodule pin 或证据充分的本地生成命令返回 `multi-repo-commit-boundary`。
140
+ 3. 仓库发现、证据冲突处理、生成入口校验、exact/retained 归属和逐步 Git 预检都由 `trellis-push` 负责;本 skill 不另行猜测依赖、拼接命令或绕过其计划。只有本地生成入口确定性、可重复、受版本控制且无外部副作用,并且计划外 dirty、retained、staged、分支和 HEAD 都满足其安全契约时才继续。
141
+ 4. 按 `trellis-push` 的计划精确提交和运行生成入口。不得裸 `git add .`、`git add -A`、push、按时间差猜归属或撤销已经成功的本地 commit。
142
+ 5. 确定性生成失败、生成结果尚未收敛或可重新规划的本地预检失败时,用 `--result failed --failure-type commit-repairable` 回写全部已完成 `--repo-commit`,然后立即 `next`。runner 前 3 次会重新发出同一个 action;每次都从真实 Git 状态重建计划,验证并跳过已完成提交,安全重跑生成,后续仓 clean 时跳过空提交。第 4 次失败进入 `commit-repair-budget-exhausted`。
143
+ 6. 全部完成后,用主仓或最后提交传 `--commit`,并为每个已完成仓库重复传入 `--repo-commit <repositories[].root>::<hash>`;同时传 `--files`、`--retained-files` 和 `--commit-message`,record 成功后立即 next。
144
+
145
+ `commit-repairable` 只用于继续执行仍然安全的本地确定性链。外部副作用风险或任何 Git 安全边界问题必须用 `blocked` 或非 repairable `failed` 立即结束当前项。部分成功提交跨 retry/resume 保留,不回滚、不 amend、不重复创建。
142
146
 
143
147
  `decisions.jsonl` 属于当前任务文件,发生决策时应进入该任务最终精确提交。任务 `task.json.status` 不因 queue item completed 而改写。
144
148
 
@@ -12,12 +12,13 @@ description: "统一 Check-All 入口:确认范围与运行上下文,按 req
12
12
 
13
13
  ## 入口职责
14
14
 
15
- 1. 确认本轮检查范围、任务材料、项目规范和运行上下文。
15
+ 1. 确认本轮检查范围、task artifacts 或 untracked state、项目规范和运行上下文。
16
16
  2. 解析 `requested_depth`,生成 `check_profile`,决定 `effective_depth=light|full`。
17
17
  3. 按有效深度读取并执行对应 profile。
18
18
  4. 全程收集普通问题到 `CHK-*`,收集低风险文档漂移到 `DOC-*`。
19
19
  5. 在最终报告前处理允许自动修复的文档漂移,并把修复内容展示在报告里。
20
20
  6. 根据 interactive / validated auto-loop 边界输出下一步或完成 runner `record + next`。
21
+ 7. untracked 上下文在最终 diff 稳定后调用 `untracked_flow.py record-check`;只有严格通过且 disposition 确认继续时才 `advance --stage spec`。
21
22
 
22
23
  ---
23
24
 
@@ -62,7 +63,7 @@ description: "统一 Check-All 入口:确认范围与运行上下文,按 req
62
63
 
63
64
  | 顺序 | 维度 | 检查内容 | 对照物 |
64
65
  | --- | --- | --- | --- |
65
- | 1 | 三件套实现 | 规划是否正确落地 | `prd.md` + 可选 `design.md` / `implement.md` |
66
+ | 1 | 三件套实现 | 规划是否正确落地 | task 的 `prd.md` + 可选 `design.md` / `implement.md`;untracked 为 `N/A` |
66
67
  | 2 | 实现假设 | API、组件、历史数据、数据流和测试假设是否成立 | 源码、真实契约、可用验证证据 |
67
68
  | 3 | 完整性与规范 | 影响面是否同步、代码是否符合 spec、验证是否通过 | 实际变更范围 + 项目 spec |
68
69
 
@@ -23,9 +23,9 @@ git log --oneline -10
23
23
 
24
24
  如果确认范围内确实无变更,提示用户并终止。
25
25
 
26
- ### 0.2 读取任务与规范
26
+ ### 0.2 读取工作上下文与规范
27
27
 
28
- 读取当前任务:
28
+ 存在当前 task 时读取:
29
29
 
30
30
  - `prd.md`;没有时三件套实现维度标记 `N/A`。
31
31
  - `design.md`(若存在)。
@@ -35,6 +35,14 @@ git log --oneline -10
35
35
 
36
36
  不得只依赖 session 摘要推断规划内容,必须读取实际文件。
37
37
 
38
+ 没有当前 task 时运行 `python3 ./.trellis/scripts/untracked_flow.py status --verbose`:
39
+
40
+ - `hit`:读取 work id、summary、stage、scope、baseline/current fingerprint 和已有验证证据;三件套实现维度标记 `N/A`,其余维度仍对实际 diff 与相关 spec 负责。
41
+ - `miss`:仅当用户明确要求检查一个无状态的已知 diff 时继续,并把工作上下文缺失列为风险;否则停止并回到 Request Triage。
42
+ - `error` 或 workspace drift:按阻塞报告,禁止用聊天摘要恢复或覆盖状态。
43
+
44
+ untracked 检查必须处于 `stage=check`,且只读取个人 check 偏好,不创建 task-scoped route decision。
45
+
38
46
  ### 0.3 验证运行上下文
39
47
 
40
48
  默认 `context=interactive`。只有调用方声称来自 auto-loop 时,才通过 runner 的 `status` / `next` 验证以下事实:
@@ -6,6 +6,8 @@ Full 是完整验收映射和全影响面审查。只有 `check_profile.effectiv
6
6
 
7
7
  ## Step 1:对照规划三件套检查实现
8
8
 
9
+ untracked 上下文没有 task artifacts,本 Step 标记 `N/A`;不得把 summary、scope 或聊天记录当成 PRD。仍须完整执行 Step 2 与 Step 3,并对实际 diff、相关 spec、状态机证据和多仓分发边界负责。
10
+
9
11
  ### 1.1 验收依据
10
12
 
11
13
  - PRD Requirement / Acceptance Criteria:行为基线。
@@ -20,6 +20,8 @@ Light 是局部且可穷举的检查,不是“少看一点”的检查。只
20
20
 
21
21
  ## 维度 1:三件套实现
22
22
 
23
+ untracked 上下文没有 task artifacts,本维度标记 `N/A`,不得根据事项摘要伪造验收条目;直接进入实现假设和完整性/规范检查。
24
+
23
25
  只提取受影响的 PRD / design / implement 条目。每条必须记录来源位置,并阅读对应实现后判断:
24
26
 
25
27
  - 需求、AC、业务规则是否被本次局部变更影响;
@@ -33,7 +33,7 @@ interactive 模式完成所有可继续检查和允许的 `DOC-*` 自动修复
33
33
 
34
34
  [<通过/未通过/阻塞>] <N> 个维度 · CHK <N> · 自动修复 DOC <N> · P0 <N> / P1 <N> / P2 <N> · 验证 <通过>/<总数>
35
35
 
36
- 任务:<任务名称或无活动任务>
36
+ 工作:<任务名称 | Untracked work: work-id | 无活动工作>
37
37
  范围:<文件数与层级摘要;包含自动修复产生的文档 diff>
38
38
  画像:requested=<auto/light/full> · effective=<light/full> · confidence=<high/fallback-full/escalated> · <原因摘要>
39
39
  结论:<一句话结论>
@@ -94,7 +94,7 @@ interactive 模式完成所有可继续检查和允许的 `DOC-*` 自动修复
94
94
 
95
95
  用户选择修复范围后:
96
96
 
97
- 1. 主会话复用当前任务已有的合法 implement route,批量修复选中的无歧义 `CHK-*`;不存在合法 implement route 时先进入 `trellis-route(target=implement)`,不得自行默认 inline/subagent。
97
+ 1. 主会话复用当前 task 已有的合法 implement route;untracked 则重新直接读取个人 pref。不存在合法 route 时进入 `trellis-route(target=implement)`,不得自行默认 inline/subagent。
98
98
  2. 修复过程中不对每个问题重复确认。
99
99
  3. 新增业务歧义、破坏性风险或范围扩张时才暂停,并一次性说明受影响问题。
100
100
  4. 完成定向验证后复用当前 check route 重新执行 Check-All。
@@ -125,6 +125,8 @@ interactive 模式完成所有可继续检查和允许的 `DOC-*` 自动修复
125
125
 
126
126
  检查通过后的动作由下方 `Interactive Post-Check Stop Gate` 判断:普通交互停止等待,符合 direct Git 严格通过条件时同轮进入 Phase 3.3 `trellis-update-spec`,再到 Phase 3.4 `trellis-push`。仍有 `CHK-*` 时停留在修复/重检循环。
127
127
 
128
+ untracked 在最终报告前调用 `untracked_flow.py record-check`:严格通过记录 `pass`,有问题记录 `findings`,部分验证记录 `partial`,真正阻塞记录 `blocked`。普通严格通过但尚未继续时保持 `stage=check`;只有 direct Git 同轮继续或用户后续明确继续时才 `advance --stage spec`。任何报告后的新编辑先回到 `prepare-edit`,旧检查证据随 fingerprint 失效。
129
+
128
130
  ---
129
131
 
130
132
  ## Auto-Loop Return Gate
@@ -5,7 +5,7 @@ description: "按确认的精确文件范围提交普通变更或完成已就绪
5
5
 
6
6
  # Trellis Push
7
7
 
8
- `trellis-push` 是 Phase 3.4 唯一的代码提交入口。它只负责生成最小计划、精确提交、普通推送,以及触发当前任务进度同步。
8
+ `trellis-push` 是 Phase 3.4 唯一的代码提交入口。它只负责生成最小计划、精确提交、普通推送,以及在 task 上触发进度同步或在 untracked 上完成状态清理。
9
9
 
10
10
  ## 职责边界
11
11
 
@@ -13,10 +13,11 @@ description: "按确认的精确文件范围提交普通变更或完成已就绪
13
13
  - 普通多仓计划可以包含本地确定性生成命令;生成后没有新增计划外文件时沿用同一次确认。
14
14
  - 普通模式把当前任务产物与更新后的 `task.json` 纳入同一次确认下的独立任务记录提交。
15
15
  - 用户明确要求“只提交不推送”时使用 `commit-only`。
16
- - auto-loop 可调用内部 `commit-only`,但必须传入已经校验过的 exact files 与 commit message;本 skill 只执行该提交。
16
+ - auto-loop 可调用内部 `commit-only`,复用本 skill 的仓库发现、动态多仓计划、确定性本地生成、精确提交和失败保留能力;不再次确认、不 push,也不执行 Step 5 的任务进度写入、进度 commit 或 progress push。Auto-Loop runner 仍按自己的状态契约写入本地 `task.json.progress`。
17
17
  - 不发起、终止或解决分支合并;只允许普通模式完成已经开始、冲突已清零且索引完全可归属的 merge commit。
18
18
  - 不处理上线核对、任务归档、会话日志或自动任务队列状态。
19
19
  - 不使用 `git add .`、`git add -A`,不要求工作区整体干净,也不提交计划外文件。
20
+ - untracked 上下文只接受 `stage=push` 且 Check-All / Update-Spec 证据与当前 workspace fingerprint 一致;不生成任务进度提交。
20
21
 
21
22
  ## 模式
22
23
 
@@ -24,9 +25,9 @@ description: "按确认的精确文件范围提交普通变更或完成已就绪
24
25
  | --- | --- | --- | --- |
25
26
  | 普通 | 展示最小计划并确认一次 | exact commit;已有 merge 就绪时完成双父提交;然后 push | 有活动任务时立即同步 |
26
27
  | 用户 `commit-only` | 展示最小计划并确认一次 | exact local commit | 跳过 |
27
- | auto-loop 内部 `commit-only` | 复用 auto-loop 预授权 | exact local commit | 跳过 |
28
+ | auto-loop 内部 `commit-only` | 复用 auto-loop 预授权 | exact local commit chain | 由 Auto-Loop runner 写本地 progress;本 skill 跳过 Step 5 |
28
29
 
29
- 内部 `commit-only` 不接受临时扩大文件范围、远端推送或其他附加动作。安全条件不满足时返回失败,由调用方决定后续状态。
30
+ 内部 `commit-only` 不接受超出当前任务证据、runner owned dirty 和 protected-retained 边界的文件,不执行远端推送或其他附加动作。安全条件不满足时返回失败,由调用方决定后续状态。
30
31
 
31
32
  ## Step 0:记录完成链证据
32
33
 
@@ -39,6 +40,8 @@ description: "按确认的精确文件范围提交普通变更或完成已就绪
39
40
 
40
41
  auto-loop 内部 `commit-only` 已由 runner 的 `run_check_all -> run_spec_update -> commit_only` 状态机和预授权保证顺序,因此不重复记录或判断本交互证据。
41
42
 
43
+ 没有活动 task 时运行 `python3 ./.trellis/scripts/untracked_flow.py status --verbose`。命中 untracked 后,以 helper 返回的 stage、scope、baseline、current fingerprint、Check-All 和 Update-Spec 证据填写上述完成链;必须为 `stage=push` 且证据仍有效。`miss` 才按既有“无活动任务”普通 Git 路径处理;`error` 或 workspace drift 停止,不从摘要猜测。
44
+
42
45
  ## Step 1:发现仓库与任务
43
46
 
44
47
  候选仓库包括:
@@ -51,7 +54,7 @@ auto-loop 内部 `commit-only` 已由 runner 的 `run_check_all -> run_spec_upda
51
54
 
52
55
  为每个候选仓库生成用户可见名称:优先使用 `.trellis/config.yaml` 中匹配的 package 名;没有配置时使用 Git top-level 目录名。`root`、`parent`、`main repo` 只允许作为输入别名,禁止直接显示在计划或结果中。
53
56
 
54
- 活动任务是可选上下文:
57
+ 活动 task 或 untracked work 都是可选上下文:
55
58
 
56
59
  ```bash
57
60
  python3 ./.trellis/scripts/task.py current --source || true
@@ -64,7 +67,7 @@ python3 ./.trellis/scripts/task_progress.py status --json || true
64
67
  git status --short --untracked-files=all -- <task-dir>
65
68
  ```
66
69
 
67
- 不得把默认 `git status --short` 可能返回的 `?? <task-dir>/` 折叠目录当成 exact file、展示条目或 pathspec。无活动任务时仍可提交相关代码,但不生成任务进度。存在活动任务时,结合 `brief.md`、`implement.md`、当前 diff 与本轮执行范围生成一行语义进度;同时识别当前任务目录中已存在且可归属的 dirty/untracked 产物,供 Step 5 生成任务记录 exact files。不得从旧进度推断 Git 动作。
70
+ 不得把默认 `git status --short` 可能返回的 `?? <task-dir>/` 折叠目录当成 exact file、展示条目或 pathspec。无活动 task 时仍可提交相关代码,但不生成任务进度。untracked 命中时,所有业务 `planned` 文件必须能由当前 state scope 与实际 diff 归属,计划同时显示 work id;scope 外文件只能保留或作为归属风险。存在活动 task 时,结合 `brief.md`、`implement.md`、当前 diff 与本轮执行范围生成一行语义进度;同时识别当前任务目录中已存在且可归属的 dirty/untracked 产物,供 Step 5 生成任务记录 exact files。不得从旧进度推断 Git 动作。
68
71
 
69
72
  ## Step 2:预检与文件归属
70
73
 
@@ -100,12 +103,25 @@ git log @{u}..HEAD --oneline 2>/dev/null || true
100
103
 
101
104
  普通模式存在活动任务时,当前任务目录中已存在且可归属的 dirty/untracked 产物不进入业务 `planned`,也不进入 `retained`;它们与预计由 helper 更新的 `<task-dir>/task.json` 组成 Step 5 的任务记录 exact files。其他任务目录和无法归属当前任务的文件仍属于 `retained` 或风险,不得顺带提交。
102
105
 
103
- 普通 `PUSH` 需要在仓库间运行本地生成命令时,首次计划同时展示命令、工作目录和后续仓预计 exact files。仅在后续仓没有 retained dirty 时使用;命令必须本地、可重复且无外部副作用。
106
+ 普通 `PUSH` 或 auto-loop 内部 `commit-only` 需要在仓库间运行本地生成命令时,计划必须包含命令、工作目录、依赖顺序和后续仓预计 exact files。执行链可包含任意数量的仓库和生成步骤,不硬编码具体仓库、两仓三阶段或命令名称。
107
+
108
+ 动态执行链按以下证据优先级生成:
109
+
110
+ 1. 当前任务 `design.md` / `implement.md` 明确记录的顺序、命令和路径。
111
+ 2. 项目 SOP/spec 中的 canonical、生成和分发约定。
112
+ 3. 受版本控制的 `package.json`、Makefile 或仓库脚本入口,以及可确认的输入输出路径。
113
+ 4. 可验证的 Git/submodule 父子关系。
114
+
115
+ 上述优先级用于发现意图和执行顺序,不允许用文档覆盖当前仓库事实。命令入口、工作目录和输出路径必须由受版本控制内容验证;任务 artifacts、SOP/spec、脚本实际行为或 Git 关系互相冲突时失败关闭。
116
+
117
+ 命令必须是受版本控制的稳定入口,并且本地、确定性、可重复、无外部副作用。工作目录和预期影响路径必须可审计;只有名称相似、mtime、目录邻近或惯例不足以执行。禁止任意 shell 字符串、管道、重定向、命令替换、push、release、deploy、archive、凭证和生产数据操作;证据不足时失败关闭。
104
118
 
105
119
  `retained` 只是内部集合名。用户可见输出统一写“保留未提交的变更(dirty)”,并逐项标注 `[untracked]`、`[unstaged]`、`[staged]`。unknown ahead、branch/upstream 异常、归属不确定等真正需要处理的事项单独进入“风险”区;普通 retained dirty 不默认视为阻塞。
106
120
 
107
121
  普通模式允许 `retained` 存在。执行前记录计划外 staged set,提交后确认这些 staged 文件仍保持原状。用户明确要求新增文件时,重新生成计划并确认,不能在执行中静默扩大范围。
108
122
 
123
+ auto-loop 内部 `commit-only` 也允许 retained dirty 存在,但每个生成/提交步骤前后都必须验证 retained exact paths 的内容摘要不变,并确认它们与 planned/generated paths 不冲突。内部模式仍要求 staged 区为空;计划外 dirty、retained 漂移、未知 staged、无法由当前计划或已记录提交解释的分支/HEAD 漂移,或归属歧义立即停止后续副作用。
124
+
109
125
  已有 merge 会提交整个索引,因此 planned 必须覆盖全部 staged paths,`retained` 中不得存在 `[staged]`;未跟踪或未暂存 retained 仍可保留。
110
126
 
111
127
  ## Step 3:展示最小计划
@@ -116,7 +132,7 @@ git log @{u}..HEAD --oneline 2>/dev/null || true
116
132
  ## Trellis Push 计划
117
133
 
118
134
  [<PUSH / PUSH · MERGE / COMMIT-ONLY>] <N> 个仓库 · <N> 个 commit · <N> 个文件 · 保留未提交 <N> · 风险 <N>
119
- [无活动任务时追加:无活动任务]
135
+ [无活动 task 时追加:无活动任务;untracked 命中时改为 `Untracked work: <work-id>`]
120
136
  顺序:<repo-a> [-> `<local generation command>`] -> <repo-b> [-> task progress]
121
137
 
122
138
  ### 完成链证据
@@ -135,7 +151,7 @@ git log @{u}..HEAD --oneline 2>/dev/null || true
135
151
 
136
152
  Push:<执行 / 跳过(commit-only)>
137
153
 
138
- [生成(仅普通多仓需要时显示):前置仓成功后,在 `<working-directory>` 运行 `<exact local command>`;预计只影响 <后续仓 exact files 或分组摘要>]
154
+ [生成(多仓需要时显示):前置仓成功后,在 `<working-directory>` 运行 `<exact local command>`;预计只影响 <后续仓 exact files 或分组摘要>]
139
155
 
140
156
  ### 保留未提交的变更(dirty,仅数量大于 0 时显示)
141
157
  - [untracked] <path>
@@ -161,19 +177,21 @@ Push:<执行 / 跳过(commit-only)>
161
177
  - 顶部仓库/commit/file 总数包含独立任务记录提交所在 Git root、该提交及其 exact files;任务记录文件使用相同的 8 文件展示阈值和展开规则。
162
178
  - 保留未提交的变更始终逐项标注 Git 状态;真正风险在独立“风险”区逐项展示。
163
179
  - 完成链证据始终显示当前状态,但不重复 Check-All 报告或 Spec review 正文;`未运行`、`已失效`、findings、blocked、部分验证或 `needs-review` 同时计入风险区。
164
- - 无活动任务或 `commit-only` 时省略进度动作。
180
+ - 无活动 task、untracked 或 `commit-only` 时省略进度动作。
165
181
  - 不重复展示检查结果、规范复核、归档或其他阶段的详细信息。
166
182
  - 生成前无法确定的内容和增删行写“生成后计算”,不得填预测值。
167
183
 
168
184
  普通多仓只确认一次。计划已展示生成命令和预计 exact files 时,命令成功且没有出现预计列表外的新 dirty path 就沿用原确认;内容、hash 或统计变化不重问。其它计划边界变化仍按 Step 4 重新规划。
169
185
 
170
- auto-loop 内部 `commit-only` 仍生成同样的逐仓执行数据用于自检和结果记录,但不再次询问用户;它不得扩展调用方给定的 exact files/message。
186
+ auto-loop 内部 `commit-only` 仍生成同样的逐仓执行数据用于自检和结果记录,但不再次询问用户;它只能在当前任务 artifacts、runner owned dirty 和 protected-retained 边界内形成 exact files/message。
171
187
 
172
188
  ## Step 4:精确提交与推送
173
189
 
174
- 每个仓库按计划顺序执行。执行前重新检查 planned files、当前分支、upstream、冲突状态和 ahead commits;任一关键条件变化都停止当前执行并重新规划。仅 `retained` 内容变化时保留并在结果中更新说明。
190
+ 每个仓库按计划顺序执行。执行前重新检查 planned files、当前分支、HEAD、upstream、冲突状态、staged、全部 dirty paths 和 retained 摘要;任一关键条件变化都停止当前执行并重新规划。普通模式仅 `retained` 内容变化时可更新说明;auto-loop 内部模式的 retained 内容必须保持不变。
191
+
192
+ 计划包含本地生成命令时,前置仓成功后按计划执行命令,再复用本节现有预检。命令成功、后续仓全部 dirty paths 都在预计 exact files 内且 retained 摘要未漂移时直接继续;否则停止并重新生成计划。预计文件最终 clean 时不强行提交。
175
193
 
176
- 计划包含本地生成命令时,前置仓成功后按计划执行命令,再复用本节现有预检。命令成功、后续仓全部 dirty paths 都在已确认的预计 exact files 内且没有其它计划边界变化时直接继续;否则停止并重新生成计划。预计文件最终 clean 时不强行提交。
194
+ auto-loop retry/resume 时,读取调用方提供的已完成仓库提交,逐个验证 repository、commit object、message 和文件集合仍符合当前任务证据,并确认当前分支/HEAD 变化可由这些提交解释。验证通过的提交直接跳过;验证失败立即 blocked,不重复提交。确定性生成入口可以安全重跑,以当前 Git 状态重新规划后续步骤。
177
195
 
178
196
  普通精确提交:
179
197
 
@@ -223,9 +241,11 @@ git push origin <current-branch>
223
241
 
224
242
  多仓执行失败时停止后续未开始仓库,保留已经成功的提交/推送,不做回滚。
225
243
 
244
+ auto-loop 内部链失败时向调用方返回全部已完成仓库提交和失败位置。只有确定性生成未收敛或仍可安全重新规划的本地预检使用 `commit-repairable`;计划外 dirty、retained 漂移、未知 staged、无法由当前计划或已记录提交解释的分支/HEAD 漂移、归属歧义和外部副作用风险必须立即 blocked。不得 reset、rebase、revert、amend 或撤销成功提交。
245
+
226
246
  ## Step 5:同步任务进度
227
247
 
228
- 仅普通模式且存在活动任务时执行。全部业务仓库成功后写完整进度;已有仓库成功而后续仓库失败时写 partial 进度,明确 completed、失败位置、next 和 notes。尚未发生成功 Git 动作就失败时,不记录虚假的 completed steps;只有父仓仍可安全提交并推送时才允许记录 failure notes。
248
+ 仅普通模式且存在活动 task 时由本 skill 执行。untracked、用户 `commit-only` 与 auto-loop 内部 `commit-only` 都跳过本 Step;Auto-Loop runner 在 action record/next 后按自身契约写入本地 `task.json.progress`,不属于这里的任务进度提交或推送。全部业务仓库成功后写完整进度;已有仓库成功而后续仓库失败时写 partial 进度,明确 completed、失败位置、next 和 notes。尚未发生成功 Git 动作就失败时,不记录虚假的 completed steps;只有父仓仍可安全提交并推送时才允许记录 failure notes。
229
249
 
230
250
  新进度固定为:
231
251
 
@@ -268,6 +288,8 @@ git push origin <current-branch>
268
288
 
269
289
  ## Step 6:结果
270
290
 
291
+ untracked 的全部已确认 Git 动作成功后,最后运行 `python3 ./.trellis/scripts/untracked_flow.py clear --reason completed --work-id <work-id>`。清理成功才报告完成链已结束;任一仓库、push 或清理失败都保留状态并报告恢复位置,禁止因部分成功伪造完成。用户 `commit-only` 的已确认动作全部成功时同样可以完成并清理。
292
+
271
293
  结果复用计划的视觉顺序,先给总览,再逐仓报告实际 commit/push,最后报告任务进度与保留 dirty:
272
294
 
273
295
  ```markdown
@@ -296,6 +318,8 @@ git push origin <current-branch>
296
318
  - [staged] <path>
297
319
  ```
298
320
 
321
+ untracked 结果用“无任务状态”替代“任务进度”,展示 work id 与 `<已清理/保留待恢复>`;不生成或暗示 task progress commit。
322
+
299
323
  部分完成时必须明确列出已成功仓库、失败仓库/步骤、当前分支和下一恢复动作。业务结果与 progress sync 状态不得合并成一个模糊结论。
300
324
 
301
325
  ## 禁止事项
@@ -13,7 +13,7 @@ description: |
13
13
 
14
14
  # Trellis 路由器:implement / check 执行模式选择
15
15
 
16
- 主 agent 进入 Phase 2.1 实现路由或 Phase 2.2 检查路由时调用本 skill。当前上下文或 session runtime state 内已有合法来源、target 匹配、且 task 等于当前任务路径的最近 route 决策时,后续实现、修复、重检默认复用该决策;没有合法决策时才进入本 skill 或同编号 fallback。提交前确实需要最终复查时,回到 Phase 2.2 并复用当前任务的合法 check route,除非用户明确要求重选。
16
+ 主 agent 进入 Phase 2.1 实现路由或 Phase 2.2 检查路由时调用本 skill。task 上下文继续使用 task-scoped session route decision;untracked 上下文只读取个人 `.trellis/.route-prefs.tmp`,不读取或写入 `route_decisions`。提交前确实需要最终复查时,回到 Phase 2.2 并按当前 subject 的同一规则解析 route。
17
17
 
18
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
 
@@ -23,9 +23,15 @@ description: |
23
23
 
24
24
  ## Step 0: 识别目标与用户意图
25
25
 
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。
26
+ 个人 route 配置只决定“已获准执行后的模式”,不是开工授权。调用 helper 前,必须确认当前 workflow 已允许进入对应 target:task implement 需要任务已完成规划确认并处于 `in_progress`;untracked implement 需要 `untracked_flow.py status` 命中当前 session;check 需要 Phase 2.2 或 untracked `stage=check`。如果仍在 planning、等待用户确认,或用户表达“等一下 / 我再想想”,停止,不读取 runtime/prefs。
27
27
 
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、ordinary summary、SessionStart 摘要、replacement history、`codex-mode`、空 `.route-prefs.tmp`、旧单值偏好、历史用户裸数字,都不能单独作为有效 route 决策。
28
+ 先用 `task.py current --source` 与 `untracked_flow.py status` 确认 subject,二者只能命中一个:
29
+
30
+ - task 命中:`scope=task`,继续使用本 skill 既有 runtime -> prefs -> auto-loop 顺序。
31
+ - 无 task 且 untracked 命中:`scope=untracked`,只使用 pref-only CLI;不得伪造 task 路径或 task artifacts。
32
+ - 二者都未命中:返回 workflow Request Triage,不展示执行 route。
33
+
34
+ task 的合法 route 决策必须能追溯到 `trellis-route`、同编号 fallback 选项、有效 `.trellis/.route-prefs.tmp`,或 route helper 校验过的 auto-loop 临时授权,并且 `task` 字段等于当前任务路径。untracked 的合法 route 只来自本次紧邻选择或 `read-pref` 命中;不写 runtime,也不接受 auto-loop 授权。用户自然语言、摘要、SessionStart 提示、`codex-mode`、空偏好或历史裸数字都不能单独作为有效 route 决策。
29
35
 
30
36
  当前上下文内已有 target 匹配、task 等于当前任务路径、且来源合法的 route 决策时,后续实现、check 发现问题、用户指出刚检查过的实现有问题、修复后重检、提交前复查均默认复用最近 implement/check 路由;除非用户明确要求重选/临时改/清除默认,不再调用本 skill。当前上下文没有 route 决策但 runtime state 命中时,本 skill 恢复该决策并输出同样的结构化 `route_decision`。如果上下文里只有上一个任务的 `route_decision`,必须忽略并重新解析当前任务。
31
37
 
@@ -49,7 +55,7 @@ Codex inline mode 只表示主会话默认直接执行,不是 route 选项过
49
55
 
50
56
  ## Step 0.5: 解析已有 route state
51
57
 
52
- 仅在没有覆盖意图、当前上下文没有 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 状态。
58
+ task 仅在没有覆盖意图、当前上下文没有 target + 当前 task 匹配的合法 `route_decision` 时调用 `resolve`,解析顺序固定为 runtime -> prefs -> auto-loop。untracked 不调用 `resolve`,每次直接调用 `read-pref`;命中即可执行,miss 才进入 Step 2。
53
59
 
54
60
  调用随本 skill 分发的 helper;不要在对话中内嵌或改写 helper 逻辑:
55
61
 
@@ -59,6 +65,14 @@ python3 .agents/skills/trellis-route/scripts/route_state.py resolve --target <im
59
65
  python3 .claude/skills/trellis-route/scripts/route_state.py resolve --target <implement|check>
60
66
  ```
61
67
 
68
+ untracked 调用:
69
+
70
+ ```bash
71
+ python3 .agents/skills/trellis-route/scripts/route_state.py read-pref --target <implement|check>
72
+ # Claude 平台若只有 .claude skill 副本,则使用:
73
+ python3 .claude/skills/trellis-route/scripts/route_state.py read-pref --target <implement|check>
74
+ ```
75
+
62
76
  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。
63
77
 
64
78
  helper 默认输出为精简 JSON,只包含 route 执行必需的 `status`、`origin`、`mode`、`source`/`reason` 等字段。需要排查完整 `decision`、session 文件、context key、任务路径、个人配置路径或写回标记时,在同一命令末尾加 `--verbose`;不要为了诊断信息额外读取 runtime 文件。
@@ -137,7 +151,7 @@ fi
137
151
 
138
152
  ## Step 2.6: 写入 route state / 默认配置
139
153
 
140
- 用户选择本次模式后,调用 helper 写入当前 session runtime。选项含“保存默认”或“更新默认”时,加 `--save-pref`,helper 会同时更新 `.trellis/.route-prefs.tmp` 并保留另一个 target 的偏好。
154
+ task 用户选择本次模式后,调用 helper 写入当前 session runtime。选项含“保存默认”或“更新默认”时,加 `--save-pref`。untracked 的“仅本次”只用于当前调用,不写任何 runtime 或偏好;“保存默认/更新默认”只调用 `write-pref`。
141
155
 
142
156
  只影响本次:
143
157
 
@@ -155,6 +169,14 @@ python3 .agents/skills/trellis-route/scripts/route_state.py write --target <impl
155
169
  python3 .claude/skills/trellis-route/scripts/route_state.py write --target <implement|check> --mode <mode> --source <trellis-route|numbered-fallback> --save-pref
156
170
  ```
157
171
 
172
+ untracked 保存 / 更新默认:
173
+
174
+ ```bash
175
+ python3 .agents/skills/trellis-route/scripts/route_state.py write-pref --target <implement|check> --mode <mode>
176
+ # Claude 平台若只有 .claude skill 副本,则使用:
177
+ python3 .claude/skills/trellis-route/scripts/route_state.py write-pref --target <implement|check> --mode <mode>
178
+ ```
179
+
158
180
  清除默认:
159
181
 
160
182
  ```bash
@@ -177,13 +199,17 @@ helper 写入规则:保留另一个 target 的 runtime 决策和偏好;覆
177
199
 
178
200
  | 路由决定 | 主 agent 应执行 |
179
201
  |---------|----------------|
180
- | `inline implement` | `Skill({skill: "trellis-before-dev"})` 加载 spec → 读任务文档 → 主线程实施 → 跑必要验证 → 回到 Phase 2.1 completion contract 解析 Pre-Check,不得在局部验证后直接结束 |
181
- | `subagent implement` | `Agent({subagent_type: "trellis-implement"})`;若 `subagent_skip_compile=true`,dispatch prompt 附加“跳过 mvn install / npm run build / tsc 等耗时编译类检查(已由主 agent 验证或最终统一执行)”;主 agent 收到结果后回到 Phase 2.1 completion contract 解析 Pre-Check |
202
+ | `inline implement` | `Skill({skill: "trellis-before-dev"})` 加载 spec;task 再读任务文档,untracked 读取 helper 状态与实际 scope → 主线程实施 → 跑必要验证 → 回到 Phase 2.1 completion contract |
203
+ | `subagent implement` | `Agent({subagent_type: "trellis-implement"})`;task 使用 `Active task:`,untracked 使用下方自包含 `Untracked work:` 契约;主 agent 收到结果后回到 Phase 2.1 completion contract |
182
204
  | `inline check-all` | `Skill({skill: "trellis-check-all"})` |
183
205
  | `subagent check-all` | 优先使用明确 audit-only 的 `trellis-check-all` agent;不存在时使用平台通用 subagent,并用下方 dispatch 契约执行本地 `trellis-check-all`。subagent 只返回 `DOC-*` 文档漂移候选,不写文件;主会话负责允许的文档自修。禁止 fallback 到会直接修改工作区的 `trellis-check` agent;无兼容 subagent 时停止并请用户改选 inline |
184
206
 
185
207
  implement 路由只决定执行位置,不拥有实现后的停止策略。无论 inline 或 subagent,focused validation 完成后都必须返回 workflow Phase 2.1 的 completion contract;由该 owner 处理 auto-loop、用户显式继续/暂缓、已有 hold 和默认立即 Check-All 的优先级。
186
208
 
209
+ ### Untracked Subagent Dispatch 契约
210
+
211
+ untracked 的 implement/check subagent prompt 第一行固定为 `Untracked work: <work-id>`,并包含事项摘要、stage、scope、baseline 仓库摘要、current fingerprint、已有验证证据、相关 spec 路径和本轮明确职责。不得写 `Active task:`,不得要求 `prd.md`、`implement.jsonl` 或 `check.jsonl`。agent 必须直接执行,不得递归 dispatch implement/check agent。
212
+
187
213
  ### Subagent Check-All Dispatch 契约
188
214
 
189
215
  使用专用或通用 subagent 时,dispatch prompt 第一行必须是当前任务路径,并包含以下完整边界:
@@ -219,8 +245,9 @@ route_decision:
219
245
  target: <implement | check>
220
246
  mode: <inline | subagent | check-all-inline | check-all-subagent>
221
247
  source: <trellis-route | route-prefs | auto-loop | numbered-fallback>
222
- scope: task
223
- task: <current task path>
248
+ scope: <task | untracked>
249
+ task: <current task path; task only>
250
+ work_id: <current untracked work id; untracked only>
224
251
 
225
252
  接下来主 agent 应当:
226
253
  - <路由表里对应的工具调用形式>
@@ -317,7 +317,20 @@ def _write_prefs(repo_root: Path, prefs: dict[str, str]) -> None:
317
317
  if value:
318
318
  lines.append(f"{target}={value}")
319
319
  path.parent.mkdir(parents=True, exist_ok=True)
320
- path.write_text("\n".join(lines) + "\n", encoding="utf-8")
320
+ fd, temp_name = tempfile.mkstemp(prefix=f".{path.name}.", suffix=".tmp", dir=path.parent)
321
+ temp_path = Path(temp_name)
322
+ try:
323
+ with os.fdopen(fd, "w", encoding="utf-8") as handle:
324
+ handle.write("\n".join(lines) + "\n")
325
+ handle.flush()
326
+ os.fsync(handle.fileno())
327
+ os.replace(temp_path, path)
328
+ except Exception:
329
+ try:
330
+ temp_path.unlink()
331
+ except FileNotFoundError:
332
+ pass
333
+ raise
321
334
 
322
335
 
323
336
  def _normalized_decision(decision: Any, target: str, current_task: str) -> dict[str, Any] | None:
@@ -643,6 +656,74 @@ def write_route(args: argparse.Namespace) -> int:
643
656
  )
644
657
 
645
658
 
659
+ def read_pref(args: argparse.Namespace) -> int:
660
+ """读取不依赖任务或 session 的个人 route 偏好。
661
+
662
+ Args:
663
+ args: 包含 target 和 verbose 的命令行参数。
664
+
665
+ Returns:
666
+ 命令退出码。
667
+ """
668
+ repo_root = _repo_root()
669
+ if repo_root is None:
670
+ return _print({"status": "miss", "reason": "not-trellis-project"})
671
+ mode = _read_prefs(repo_root).get(args.target)
672
+ if mode not in PREF_MODES[args.target]:
673
+ return _output(
674
+ args,
675
+ {"status": "miss", "reason": "no-valid-pref", "target": args.target},
676
+ {"pref_path": _rel_path(repo_root, _pref_path(repo_root))},
677
+ )
678
+ return _output(
679
+ args,
680
+ {
681
+ "status": "hit",
682
+ "target": args.target,
683
+ "mode": mode,
684
+ "source": "route-prefs",
685
+ },
686
+ {"pref_path": _rel_path(repo_root, _pref_path(repo_root))},
687
+ )
688
+
689
+
690
+ def write_pref(args: argparse.Namespace) -> int:
691
+ """写入不依赖任务或 session 的个人 route 偏好。
692
+
693
+ Args:
694
+ args: 包含 target、mode 和 verbose 的命令行参数。
695
+
696
+ Returns:
697
+ 命令退出码。
698
+ """
699
+ mode = _normalize_mode(args.target, args.mode)
700
+ if mode not in PREF_MODES[args.target]:
701
+ return _print(
702
+ {
703
+ "status": "error",
704
+ "reason": "invalid-mode",
705
+ "target": args.target,
706
+ "mode": args.mode,
707
+ }
708
+ )
709
+ repo_root = _repo_root()
710
+ if repo_root is None:
711
+ return _print({"status": "skipped", "reason": "not-trellis-project"})
712
+ prefs = _read_prefs(repo_root)
713
+ prefs[args.target] = mode
714
+ _write_prefs(repo_root, prefs)
715
+ return _output(
716
+ args,
717
+ {
718
+ "status": "written",
719
+ "target": args.target,
720
+ "mode": mode,
721
+ "source": "route-prefs",
722
+ },
723
+ {"pref_path": _rel_path(repo_root, _pref_path(repo_root))},
724
+ )
725
+
726
+
646
727
  def clear_pref(args: argparse.Namespace) -> int:
647
728
  """清除当前 target 的个人默认 route 配置。"""
648
729
  repo_root = _repo_root()
@@ -688,6 +769,17 @@ def build_parser() -> argparse.ArgumentParser:
688
769
  write_parser.add_argument("--verbose", action="store_true", help="include diagnostic paths and session metadata")
689
770
  write_parser.set_defaults(func=write_route)
690
771
 
772
+ read_pref_parser = subparsers.add_parser("read-pref", help="read a personal route preference")
773
+ read_pref_parser.add_argument("--target", choices=sorted(PREF_MODES), required=True)
774
+ read_pref_parser.add_argument("--verbose", action="store_true", help="include preference path metadata")
775
+ read_pref_parser.set_defaults(func=read_pref)
776
+
777
+ write_pref_parser = subparsers.add_parser("write-pref", help="write a personal route preference")
778
+ write_pref_parser.add_argument("--target", choices=sorted(PREF_MODES), required=True)
779
+ write_pref_parser.add_argument("--mode", required=True)
780
+ write_pref_parser.add_argument("--verbose", action="store_true", help="include preference path metadata")
781
+ write_pref_parser.set_defaults(func=write_pref)
782
+
691
783
  clear_parser = subparsers.add_parser("clear-pref", help="clear a personal route preference")
692
784
  clear_parser.add_argument("--target", choices=sorted(PREF_MODES), required=True)
693
785
  clear_parser.add_argument("--verbose", action="store_true", help="include diagnostic paths and preference metadata")