#622·Trellis

task.py archive:归档未被 git 跟踪的任务目录时自动提交失败(目录已移动、未提交)

Author: MrNine-666Created Sep 17, 2026Updated Sep 17, 2026

环境

  • @mindfoldhq/trellis CLI v0.6.17(项目内 .trellis/ 为 0.6.16)
  • Windows + PowerShell 7 + git(仓库 test 分支)
  • 平台:Pi(sub-agent-dispatch 工作流)

复现步骤

  1. python ./.trellis/scripts/task.py create "<title>" --slug <slug> —— 建出任务目录,不产生提交(目录保持 untracked)
  2. 正常做完任务、提交代码(此时任务目录仍是 ?? untracked)
  3. python ./.trellis/scripts/task.py archive <task-name>

期望

任务目录从 .trellis/tasks/<name> 移到 .trellis/tasks/archive/YYYY-MM/<name>,并产生一条 chore(task): archive <name> 提交。

实际

Archived: 09-17-portal-stat-cards-regulation-style -> archive/2026-09/
[WARN] Auto-commit failed: error: pathspec '.trellis/tasks/09-17-portal-stat-cards-regulation-style' did not match any file(s) known to git
  • 目录已移动,但没有任何提交(HEAD 未变,工作区内容与归档前一致)
  • safe_git_add 已把新归档路径 stage 进索引;因提交整体中止,工作区留下 A 状态的暂存文件(我随后手工提交才清掉)

根因(scripts/common/task_store.py::_auto_commit_archive

python
# L1441
source_was_tracked = rc == 0 and bool(tracked_out.strip())
...
# L1475  —— 对「从未被跟踪」的情况是 no-op,这一步没问题
["rm", "-r", "--cached", "--ignore-unmatch", "--", source_rel]
...
# L1500  —— 无条件把 source_rel 拼进提交 pathspec
["commit", "-m", commit_msg, "--", *paths, source_rel], cwd=repo_root

source_was_tracked 已经算出来了,但只用于几个 return 分支(return not source_was_tracked),没有参与 pathspec 构造。最终的 git commit -- <paths> <source_rel> 仍带着一个已经不在索引/工作区里的路径,git 对 commit pathspec 要求必须匹配到内容,于是整条提交被中止 —— 连新归档路径一起被带崩。

(对照:git rm --cached --ignore-unmatch 显式处理了 untracked 情况,说明这条分支是被考虑过的,只是 commit 侧漏了。)

建议修复

只在源目录确实被跟踪时才把 source_rel 加进 commit pathspec:

python
commit_paths = [*paths, source_rel] if source_was_tracked else list(paths)
rc, _, err = run_git_retry_index_lock(
    ["commit", "-m", commit_msg, "--", *commit_paths], cwd=repo_root
)

或者对 pathspec 先做一次存在性过滤再提交。

影响

  • 静默半归档:磁盘上目录已归档,但历史里没有归档提交;task.json 已写 status=completed,任务也从 task.py list 消失,容易被误判为「已完整归档」。
  • 脚本确实有兜底输出(L1389 "Archive moved on disk, but git auto-commit did not complete. "),但走 pathspec 报错分支时不会打印它,而且会留下非预期的 staged 状态。
  • 影响面:任何「task create 后未单独提交任务目录、直接做完再 archive」的流程。这条路径在实践里很常见(create 本身不提交,而开发者往往只在收尾时提交一次代码)。

临时绕过

bash
git add -- .trellis/tasks/archive/YYYY-MM/<name>
git commit -m "chore(task): archive <name>" -- .trellis/tasks/archive/YYYY-MM/<name>

(即脚本自己在 L1548 给出的手工提示。)

补充

如果「未跟踪的任务目录在 archive 时不做提交」是有意设计,那至少应跳过 commit 而不是报错中止,并且不要留下 staged 状态。