fix(tasks): make status git-authoritative, not Vikunja

修掉一处会让并行保护失效的设计缺口:AGENTS.md 声明「状态」权威在 Vikunja,
但离线门禁的检查 1 读的是 frontmatter 的 status,两者之间没有任何同步。
有人在看板上拖了卡片,frontmatter 不变,门禁就用过期数据放行了。

status 的权威定为 git frontmatter,理由与 write_paths 相同:它是判定
「两个活跃任务不得写同一路径」的输入,而门禁必须离线可跑;status 变更
决定谁能碰哪些文件,本来就该产生 commit。

- AGENTS.md:把 status 从 Vikunja 权威列表移入 git 原生表,并说明 bucket
  与 done 仅为人类视图,不一致时以 git 为准
- agent-context.json:tracker.git_native_fields 增加 status
- validate_agent_context.py:强制 git_native_fields 必须含 status,
  已用反例验证缺失时报错
- vikunja_export.py:新增只读漂移检测,导出时比对 frontmatter status 与
  Vikunja done,不一致则提示;只提示不修正,不反向写回
- docs/tasks/README.md、T-008 方案第 1/2 节:同步口径

顺带解决了窄 token 时期的 bucket 401 遗留问题——status 权威在 git,
agent 不再依赖 bucket 移动来表达状态。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
QiuSW
2026-08-03 17:17:35 +08:00
co-authored by Claude Opus 5
parent ed489bd13e
commit 3c458bcf5b
6 changed files with 78 additions and 12 deletions
+16 -4
View File
@@ -80,13 +80,25 @@ cmbuyer 是一个自动化采购系统:**采购服务**(网页端,`admin/`
## 任务状态存放在哪
任务的**协调状态**(标题、状态、标签、依赖、方案正文、执行记录)权威在自建 Vikunja 的
任务的**叙述性内容**(标题、标签、依赖、方案正文、验收要点、执行记录)权威在自建 Vikunja 的
`cmbuyer` 项目;`docs/tasks/T-XXX.md` 里两行 `VIKUNJA EXPORT` 标记之间的内容是它的
**单向投影**,由 `scripts/vikunja_export.py` 覆盖写入,不要手工编辑。
**`write_paths`、`## 边界` 与安全边界条目的权威始终在 git**,不迁往 Vikunja。理由见
本文第 2 条:安全边界能不能收紧靠 `git diff` 逐条复核,权威一旦搬到远端,放宽边界的改动
在 diff 里只呈现为「导出内容更新」,审计链就断了。
**以下四项的权威始终在 git,不迁往 Vikunja:**
| 项 | 位置 | 为什么不能搬 |
| --- | --- | --- |
| `status` | frontmatter | 门禁靠它判定谁能写哪些路径,且必须离线可跑;权威在远端等于校验要联网 |
| `write_paths` | frontmatter | 同上,是并行安全的判定输入 |
| `context_ref` / `work_branch` | frontmatter | 锚定 commit,离开 git 就失去意义 |
| `## 边界`与安全边界条目 | 正文区块外 | 见本文第 2 条:能否收紧靠 `git diff` 逐条复核 |
安全边界的权威一旦搬到远端,放宽边界的改动在 diff 里只呈现为「导出内容更新」,
审计链就断了。`status` 同理:它不是看板装饰,是决定并行写入安全的协调契约,
每次变更都应当产生一个 commit。
Vikunja 的 bucket 与 `done` 标志是**人类视图**,不是判定依据。两者不一致时以 git 为准;
`scripts/vikunja_export.py` 会在导出时只读比对并提示漂移,但不会反向写回。
只读任务内容不需要接入 Vikunja——导出产物就在仓库里,`git clone` 即可。只有写状态和
执行记录才需要配置 MCP。