feat(governance): automate harness consistency checks (phase 3)
Harness governance / validate (push) Has been cancelled

This commit is contained in:
chengma
2026-07-14 13:05:19 +08:00
parent 0a09deacee
commit 1d3428a288
22 changed files with 2149 additions and 60 deletions
+2 -2
View File
@@ -45,7 +45,7 @@
4. 运行 `./init.sh`(Windows 原生 PowerShell 用 `./init.ps1`):统一安装、验证、打印启动命令;如果脚本提示命令未替换,先配置脚本顶部三个命令。
5. 跑一条基础 smoke / 端到端路径,确认基线没坏。
6. **如果基线已坏,先修基线**,不要在坏的起点上叠新功能。
7. 基线绿了,再从 `docs/tasks/` 为当前 agent 领取唯一任务(路线图见 [`06-tasks.md`](06-tasks.md));启用 Gitea 时由 dispatcher 串行分配并取得原子 claim。
7. 基线绿了,再从 `docs/tasks/` 为当前 agent 领取唯一任务(路线图见 [`06-tasks.md`](06-tasks.md));启用 Gitea 时由 dispatcher 串行分配并创建 claim 标记。
## 当前阶段
@@ -66,7 +66,7 @@
- 每个 agent 只领取一个 frontmatter `status: TODO` 且依赖均 `DONE` 的任务文件,取编号最靠前的;项目可并行多个 `write_paths` 互不重叠的任务。
- 若 `docs/tasks/` 暂无可领任务,先按 [`06-tasks.md`](06-tasks.md) 路线图把下一个建议任务落成任务文件,再领取。
- 未启用 Gitea 时,开始前在独立分支 / worktree 把该文件 frontmatter 的 `status` 改为 `DOING`。
- 启用 Gitea 时,由 dispatcher 按 [`gitea-collaboration.md`](gitea-collaboration.md) 串行检查写路径并原子创建 `claims/T-<编号>`;worker 只接受已读回确认的分配。标签、assignee 和更新后读回不能代替同任务领取锁。
- 启用 Gitea 时,由 dispatcher 按 [`gitea-collaboration.md`](gitea-collaboration.md) 串行检查写路径并创建 `claims/T-<编号>` 防御性标记;worker 只接受已读回确认的分配。不要把标签、assignee、读回或普通 create-branch API 单独当作并发锁。
- 本轮只完成这一个任务;验收通过后改为 `DONE`。
- **执行记录写进该任务文件的 `## 执行记录`**(改了什么、跑了什么验证、结果、决策)。
- 若项目现实发生变化(启动/验证路径、目录结构、blocker),覆盖更新 [`current-state.md`](current-state.md);未启用 Gitea 时以任务文件 frontmatter 为状态权威,启用后以 Issue 为实时状态,不逐任务改写快照。
+6 -1
View File
@@ -30,7 +30,7 @@
- [当前实现状态](current-state.md):可覆盖的当前快照,记录仓库现实状态、可运行命令和下一步可做任务。
- [Agent 上下文清单](agent-context.md) / [`agent-context.json`](agent-context.json) / [`Schema`](agent-context.schema.json):按任务类型选择文档、用提交 / 文件 SHA 避免重复读取。
- [Gitea MCP 接入](gitea-mcp.md):可选的共享文档、Issue / PR 协调、安全配置和断连降级规则。
- [Gitea 多 Agent 协作](gitea-collaboration.md):可选的任务映射、原子 claim、写路径防撞和 PR 状态协议。
- [Gitea 多 Agent 协作](gitea-collaboration.md):可选的任务映射、串行分配、防重复 claim 和 PR 状态协议。
- [收尾检查清单](clean-state-checklist.md):会话结束前逐项检查,保证下一轮无需人工修复即可继续。
- [方法对照表](method-map.md):失败模式 → 首要修复 → 工件;出问题先查这里对症补工件。
- [评审评分表](evaluator-rubric.md):单次会话输出的结构化评审(6 维 0-2 分 + 校准说明)。
@@ -38,7 +38,12 @@
- [`../init.sh`](../init.sh) / [`../init.ps1`](../init.ps1):标准启动与验证入口脚本(根目录),统一安装、验证和启动命令。按操作系统二选一:WSL / Git Bash / macOS / Linux 用 `init.sh`,Windows 原生 PowerShell 用 `init.ps1`;换技术栈只改脚本顶部三个命令变量;未替换前脚本会主动失败,避免把示例命令误当真实项目命令。
- [`../scripts/validate_agent_context.py`](../scripts/validate_agent_context.py):零第三方依赖校验上下文清单、Schema 和仓库相对路径。
- [`../scripts/setup_gitea_labels.py`](../scripts/setup_gitea_labels.py):默认只读预览远端差异、显式写入的 Gitea 协作标签初始化脚本。
- [`../scripts/validate_harness_governance.py`](../scripts/validate_harness_governance.py):离线检查导航、链接、任务、模板、工作流和敏感信息。
- [`../scripts/audit_gitea_coordination.py`](../scripts/audit_gitea_coordination.py):只读审计远端任务映射、状态、分支、PR、写路径和过期 claim。
- [`../scripts/test_gitea_claim_race.py`](../scripts/test_gitea_claim_race.py):显式写入并安全清理的 claim 分支并发兼容性 smoke。
- [`../tests/test_governance.py`](../tests/test_governance.py):标准库治理回归测试。
- [Gitea Issue 模板](../.gitea/ISSUE_TEMPLATE/task.md) / [PR 模板](../.gitea/PULL_REQUEST_TEMPLATE.md):任务映射、写路径和验证证据字段。
- [Gitea Actions 工作流](../.gitea/workflows/harness-governance.yml):push / PR 离线治理模板;实际执行依赖仓库 Actions 和 runner。
## 任务 / 进度 / 当前状态
+1 -1
View File
@@ -31,7 +31,7 @@
推荐随后补齐:`docs/01-vision.md`、`docs/02-requirements.md`、`docs/03-tech-stack.md`、`docs/04-architecture.md`、`docs/api.md`、`docs/routes.md`、`docs/clean-state-checklist.md`;`progress.md` 可选(历史归档 / 项目级大事记)。
需要 Gitea 多 Agent 协作时,再复制 `docs/gitea-mcp.md`、`docs/gitea-collaboration.md`、`.gitea/` 模板和 `scripts/setup_gitea_labels.py`;先只读预览远端标签差异,再由维护者显式 `--apply`。
需要 Gitea 多 Agent 协作时,再复制 `docs/gitea-mcp.md`、`docs/gitea-collaboration.md`、`.gitea/` 模板、`scripts/setup_gitea_labels.py`、`scripts/audit_gitea_coordination.py`、离线治理脚本和测试;先只读预览远端标签差异,再由维护者显式 `--apply`。Actions 工作流仅在仓库已启用 Actions 且 runner 可用时生效。
## 接入步骤
+1
View File
@@ -14,5 +14,6 @@
- [ ] 代码处于可安全恢复的状态(必要时已提交,提交信息清晰)。
- [ ] 本轮实际修改没有超出任务 `write_paths`,也没有与其他活跃任务发生路径重叠。
- [ ] 启用 Gitea 时,Issue 的唯一 `status/*`、claim / 工作分支、PR 和任务状态彼此一致;未完成任务没有误删 claim。
- [ ] 已运行 `python scripts/validate_harness_governance.py`;启用且可连接 Gitea 时,还运行了只读 `python scripts/audit_gitea_coordination.py --repo 【owner/repo】 --dispatcher 【Gitea登录名】`。
任意一项不满足,就先补到满足,再结束会话。
+1 -1
View File
@@ -61,7 +61,7 @@
2. 读 `docs/00-ai-start-here.md`。
3. 读 `docs/05-coding-rules.md`。
4. 在 `docs/tasks/` 找到 frontmatter `status: TODO` 且依赖均 `DONE` 的任务文件;暂无任务时,先按 `docs/06-tasks.md` 路线图落成任务文件。
5. 未启用 Gitea 时,在独立分支 / worktree 把任务改为 `DOING`;启用 Gitea 时,先按 `gitea-collaboration.md` 由 dispatcher 完成原子 claim 和路径分配,worker 读回成功后再开始。
5. 未启用 Gitea 时,在独立分支 / worktree 把任务改为 `DOING`;启用 Gitea 时,先按 `gitea-collaboration.md` 由 dispatcher 串行完成路径分配和 claim 标记,worker 读回成功后再开始。
## 维护规则
+29 -10
View File
@@ -8,7 +8,7 @@
| --- | --- | --- |
| `docs/tasks/T-<编号>.md` | 任务规格、依赖、允许写路径、验收标准、可审计执行证据 | Token、实例地址、临时聊天 |
| Gitea Issue | 实时状态、领取者、阻塞、结构化 claim / 续租记录 | 需求正文的唯一副本 |
| `claims/T-<编号>` 分支 | 唯一领取锁;分支存在表示任务已被领取 | 工作提交 |
| `claims/T-<编号>` 分支 | 防御性领取标记;分支存在表示 dispatcher 已分配任务 | 工作提交、跨 dispatcher 的线性化锁 |
| `agent/<agent-id>/T-<编号>` 分支 | 单个 agent 的任务提交 | 其他任务的顺手修改 |
| Pull Request | 评审、验证证据、合并决策 | 未进入 Git 的隐含上下文 |
@@ -44,13 +44,13 @@ Issue 是实时状态权威;默认分支尚未合入工作提交时,其任
因此 dispatcher 能从默认分支可靠定位任务 ↔ Issue;没有双向映射或没有 `status/todo` 的任务都不可领取。
## 串行分配与原子领取
## 串行分配与防重复领取
仅修改 assignee / `status/doing` 再读回不是原子操作:两个 agent 可能先后覆盖并各自读到成功。MVP 指定一个 dispatcher(主 agent 或维护者)串行执行分配;worker 不并发自选任务。dispatcher 再使用 Gitea “同名分支只能创建一次”的约束,防止同一任务因重试或旁路操作被重复领取:
仅修改 assignee / `status/doing` 再读回不是原子操作:两个 agent 可能先后覆盖并各自读到成功。MVP 的互斥保证来自单一 dispatcher(主 agent 或维护者)串行执行分配;worker 不并发自选任务。claim 分支用于识别已分配任务并拦截顺序重试 / 常见旁路,不把 Gitea 的普通 create-branch API 当作线性化锁:
1. 读取默认分支任务文件和对应 Issue,确认双向映射、依赖均为 `DONE`、Issue 为 `status/todo`,且目标 worker 没有其他活跃任务。
2. 读取默认分支头提交 SHA,记为 `context_ref`。串行检查所有活跃预留的 `write_paths`,不得与本任务重叠。
3. 从精确的 `context_ref` 原子创建 `claims/T-<编号>`。创建成功者获得该任务锁;收到 `409` 或“分支已存在”即停止,不得仅因分支 SHA 相同就判定成功。
3. 从精确的 `context_ref` 创建 `claims/T-<编号>` 防御性标记。若已存在、返回非成功或状态不确定就停止并人工核查;并发冲突在不同版本中可能表现为 `409` 或 `5xx`,不得自动无限重试,也不得仅因分支 SHA 相同就判定本次分配成功。
4. 创建 `agent/<agent-id>/T-<编号>` 工作分支,更新 Issue 为 `status/doing`,按项目规则设置 assignee,并追加结构化 claim 评论。
5. dispatcher 读回 Issue 和两个分支;不一致时先修复协调状态,不把任务交给 worker。
6. worker 在独立 worktree 读回分配结果,再把工作分支任务文件更新为 `DOING`,写入 `context_ref`、claim / 工作分支和已接受的 `write_paths`;提交只触碰允许路径。
@@ -63,11 +63,13 @@ Issue 是实时状态权威;默认分支尚未合入工作提交时,其任
CLAIM
task: T-123
claimed_by: 【agent-id】
allocated_by: 【dispatcher-id】
allocated_by: 【dispatcher 的 Gitea 登录名】
context_ref: 【40 位提交 SHA】
claim_branch: claims/T-123
work_branch: agent/【agent-id】/T-123
write_paths: 【仓库相对路径列表】
write_paths:
- docs/tasks/T-123.md
- 【其他仓库相对路径】
claimed_at: 【RFC 3339 时间】
lease_until: 【RFC 3339 时间】
```
@@ -76,10 +78,10 @@ lease_until: 【RFC 3339 时间】
## 写路径防撞
- 默认分支任务文件定义初始 `write_paths`;领取后,最新被 dispatcher 接受的结构化 claim / scope 评论与工作分支任务文件共同定义活跃预留。二者不一致时暂停工作。
- 默认分支任务文件定义初始 `write_paths`;领取后,由配置的 dispatcher Gitea 身份发布、且 `allocated_by` 与评论作者一致的最新完整 CLAIM / CLAIM RENEWAL,与工作分支任务文件共同定义活跃预留。二者不一致时暂停工作。
- `write_paths` 必须列出任务文件本身及预期修改的文件或目录;共享配置、锁文件、导航文件也要列入。
- 两条路径相同,或一条是另一条的目录前缀,视为重叠;活跃任务不得存在重叠路径。
- 发现必须修改范围外文件时,先停止并在 Issue 提议扩展范围;dispatcher 串行复查其他活跃预留,接受后追加结构化 scope 评论,worker 同步更新工作分支任务文件,二者都完成后才能继续。
- 发现必须修改范围外文件时,先停止并在 Issue 提议扩展范围;dispatcher 串行复查其他活跃预留,接受后追加包含全部字段和新路径的 `CLAIM RENEWAL`,worker 同步更新工作分支任务文件,二者都完成后才能继续。审计始终以最后一个完整 CLAIM 块为准。
- 活跃任务由 Issue 的 `status/doing`、`status/blocked`、`status/review` 判定。每个 agent 同时最多一个活跃任务;项目可以并行多个写路径互不重叠的任务。
建议 worktree 命令:
@@ -101,10 +103,18 @@ git worktree add ../【项目】-T-123 -b agent/【agent-id】/T-123 origin/agen
## 过期 claim 与断连
- agent 应在 `lease_until` 前用新评论续租;续租不更换 claim 分支。
- worker 应在 `lease_until` 前请求续租;dispatcher 串行复查后,由自己的 Gitea 身份发布包含全部字段的 `CLAIM RENEWAL`。单次租期最长 24 小时,续租不得更换 `task`、`claimed_by`、`allocated_by`、`context_ref`、claim / 工作分支;审计以最后一个由配置 dispatcher 发布的有效块为准。
- claim 过期不等于可以自动抢占。维护者先检查 Issue 最后活动、工作分支新提交和 PR,再评论回收原因并人工删除 claim 分支。
- Gitea / MCP 断连时,只能继续已经确认归属自己的任务;不能领取新任务、释放锁或猜测远端状态。
只读检测命令:
```powershell
python scripts/audit_gitea_coordination.py --repo 【owner/repo】 --dispatcher 【Gitea登录名】
```
从默认分支的 clean checkout 运行审计。`--dispatcher`(或非敏感环境变量 `GITEA_DISPATCHER_LOGIN`)指定唯一可信的 dispatcher Gitea 登录名;审计只接受该账号发布且 `allocated_by` 一致的 CLAIM。它会核对标签、任务依赖、任务 ↔ Issue、claim / 工作分支、PR、活跃写路径和 `lease_until`,不会写远端。发现过期 claim 后不自动删除:维护者先查 Issue 最后活动、分支新提交和 PR,再评论回收原因,确认无人继续工作后才通过 UI 或受控 REST 删除。
## 初始化标签
先预览,再显式写入:
@@ -118,4 +128,13 @@ python scripts/setup_gitea_labels.py --repo 【owner/repo】 --apply
## 并发验收
在专用测试任务上让两个进程同时创建同一个临时 claim 分支,验收结果必须是恰好一个 `201`、另一个 `409`。测试前后均需人工确认分支名,清理由受控 REST / UI 完成;不得在业务任务上试验。
可用 `python scripts/test_gitea_claim_race.py --repo 【owner/repo】 --apply` 在唯一 `claims/__probe__/race-*` 临时分支做兼容性 smoke,期望恰好一个 `201`、一个 `409`。脚本只在名称前缀和 SHA 都符合预期时清理并复查 404。一次 smoke 结果不能证明 create-branch 线性化;无论结果如何,MVP 仍依赖 dispatcher 串行分配。不得在业务任务分支上试验。
## 自动化与升级阈值
- `python scripts/validate_harness_governance.py` 完全离线检查上下文清单、导航、本地链接、任务 frontmatter / 依赖 / 写路径、Gitea 模板和已跟踪文本中的敏感值。
- `.gitea/workflows/harness-governance.yml` 在 push / PR 运行标准库测试和离线检查,不注入本机长期 PAT,也不运行远端审计。平台仍会提供 job token,工作流用 `permissions: read-all` 和 `persist-credentials: false` 收窄权限与留存。
- Actions 模板只有合入默认分支、仓库启用 Actions 且带 Python 3.10+ 的 `ubuntu-latest` runner 可用时才会真正执行;内网 runner 还要能取得 `actions/checkout@v4`。没有 runner 时,以相同本地命令作为验收证据,不宣称 CI 已跑绿。
- 退出码统一:`0` 通过,`1` 发现一致性问题,`2` 配置、网络或运行前提缺失。敏感信息检查只输出规则、文件和行号,不回显命中正文。
MVP 不实现 webhook、协调服务或独立 dashboard。只有出现以下任一信号才重新评估:单项目约 20 个以上并发任务、dispatcher 成为持续瓶颈、跨仓库聚合成为刚需、重复出现路径分配竞态,或审计 / 合规要求集中查询。届时优先增加原子 allocation 服务和 webhook 索引,再评估只读 dashboard;不把前端看板当作并发控制器。
+21 -1
View File
@@ -17,6 +17,9 @@
GITEA_URL=【Gitea 实例根地址,不含 /api/v1】
GITEA_TOKEN=【最小权限 Personal Access Token】
# 启用远端协调审计时设置;不是秘密:
GITEA_DISPATCHER_LOGIN=【唯一 dispatcher 的 Gitea 登录名】
# 仅当团队明确接受 HTTP 下 Token 明文传输风险时设置:
GITEA_ALLOW_INSECURE_HTTP=1
@@ -94,6 +97,23 @@ Gitea 中的文件与本地 `docs/` 是同一 Git 工件的远端与 checkout,
多 agent 协作时遵循 [`gitea-collaboration.md`](gitea-collaboration.md):
- 任务文件保存规格和长期证据,Issue 保存实时状态,PR 保存评审与合并决策。
- 领取互斥依赖唯一 `claims/T-<编号>` 分支;assignee、`status/doing` 和读回仅作状态确认。
- 领取互斥依赖 dispatcher 串行分配;`claims/T-<编号>` 是防御性标记,assignee、`status/doing` 和读回仅作状态确认。
- MVP 由单一 dispatcher 串行分配任务并检查 `write_paths`,每个 worker 使用 `agent/<agent-id>/T-<编号>` 和独立 worktree;每任务 claim 只解决同任务重复领取,不单独保证跨任务路径互斥。
- MCP 可创建 claim / 工作分支,但当前没有创建标签或删除分支工具。标签用 `python scripts/setup_gitea_labels.py --repo 【owner/repo】 --apply` 幂等初始化;过期 claim 由维护者通过 UI 或受控 REST 人工回收。
## 治理检查
离线检查不需要 Token,可放进 Gitea Actions:
```powershell
python -m unittest discover -s tests -p "test_*.py"
python scripts/validate_harness_governance.py
```
远端一致性检查单独运行,严格只读:
```powershell
python scripts/audit_gitea_coordination.py --repo 【owner/repo】 --dispatcher 【Gitea登录名】
```
远端审计区分“不一致”(退出码 1)和配置 / 网络 / 权限失败(退出码 2),并验证 dispatcher 评论身份、任务依赖和过期 claim;`--dispatcher` 可由非敏感环境变量 `GITEA_DISPATCHER_LOGIN` 代替。它不会更新标签、关闭 Issue、合并 PR 或删除分支。
+3 -1
View File
@@ -17,8 +17,10 @@
| 文档堆叠失控 | 入口文件越来越长,"每次失败加一句" | 渐进披露,入口保持薄 | [`00-ai-start-here.md`](00-ai-start-here.md) + 拆分到具体文档 |
| 每轮全量重读 | 多 agent 反复拉取全部文档,慢且容易混入无关上下文 | 用任务路由和提交 / 文件 SHA 增量读取 | [`agent-context.md`](agent-context.md) + [`agent-context.json`](agent-context.json) |
| 多 agent 抢改任务文件 | 多个 agent 并发时抢改同一个看板/进度文件,出现"读到旧版本"、ID 撞号、合并冲突 | 一任务一文件(默认模式已内建),执行记录进任务文件,不逐任务改共享收尾文件 | [`tasks/README.md`](tasks/README.md) |
| 多 agent 重复领取 | 两个 agent 同时把同一 Issue 改为 doing,读回后都以为成功 | 用唯一 claim 分支做原子锁,标签只展示状态 | [`gitea-collaboration.md`](gitea-collaboration.md) |
| 多 agent 重复领取 | 两个 agent 同时把同一 Issue 改为 doing,读回后都以为成功 | 由 dispatcher 串行分配,claim 分支只作防御性标记,标签只展示状态 | [`gitea-collaboration.md`](gitea-collaboration.md) |
| 多 agent 写路径碰撞 | 不同任务同时修改同一目录或共享配置,合并时才发现冲突 | dispatcher 串行声明 / 比较 `write_paths`,worker 使用独立 worktree | [`gitea-collaboration.md`](gitea-collaboration.md) + [`tasks/README.md`](tasks/README.md) |
| claim 长期占用 | Issue 仍 doing,但 agent 已退出或分支无活动,后续任务无法分配 | 只读审计 `lease_until`,人工核实后回收,不自动抢占 | [`gitea-collaboration.md`](gitea-collaboration.md) + [`../scripts/audit_gitea_coordination.py`](../scripts/audit_gitea_coordination.py) |
| 规则悄悄漂移 | 导航、任务元数据、模板或敏感配置在多轮提交后不一致 | 用同一离线治理命令在本地和 Actions 检查 | [`../scripts/validate_harness_governance.py`](../scripts/validate_harness_governance.py) |
## 使用原则
+4 -3
View File
@@ -40,6 +40,7 @@ write_paths: # 允许修改的仓库相对路径
## 方案
## 验收要点
## 边界(不改什么)
## 协作约束
## 执行记录
```
@@ -52,7 +53,7 @@ write_paths: # 允许修改的仓库相对路径
- **执行记录写进本任务文件的 `## 执行记录` 一节**(改了什么、跑了什么验证、结果、决策)——不逐任务追加共享的 `progress.md`(可选历史归档)、也不逐任务覆盖 `current-state.md`(项目级快照,只在启动/验证路径、目录结构或 blocker 变化时更新)。
- **只改自己那个任务文件**;不要编辑别人正在做的任务文件。
未启用 Gitea 时,在独立分支 / worktree 中把任务文件从 `TODO` 改为 `DOING` 即可。启用 Gitea 时,必须先按 [`../gitea-collaboration.md`](../gitea-collaboration.md) 原子创建唯一 `claims/T-<编号>` 分支;assignee、标签和“更新后读回”都不能代替领取锁。
未启用 Gitea 时,在独立分支 / worktree 中把任务文件从 `TODO` 改为 `DOING` 即可。启用 Gitea 时,必须先按 [`../gitea-collaboration.md`](../gitea-collaboration.md) 由 dispatcher 串行分配并创建 `claims/T-<编号>` 防御性标记;assignee、标签、读回和普通 create-branch API 都不能单独提供并发互斥。
## 与 Gitea Issue / PR 的映射(可选)
@@ -60,7 +61,7 @@ write_paths: # 允许修改的仓库相对路径
- 先把任务文件合入默认分支,再创建 Issue;随后把 Issue 编号回填任务文件并合入默认分支,最后才添加 `status/todo`。映射未完成的 Issue 不可领取。
- Issue、claim 分支、工作分支和 PR 都携带同一个 `T-<编号>`;不得用一个 PR 顺带完成多个任务。
- 工作分支命名为 `agent/<agent-id>/T-<编号>`,每个 agent 使用独立 worktree。
- MVP 由一个 dispatcher / 主 agent 串行分配任务。唯一 claim 分支保证同一任务不被重复领取,dispatcher 的串行检查保证不同任务的 `write_paths` 不冲突。
- MVP 由一个 dispatcher / 主 agent 串行分配任务,以此保证同一任务不被重复领取,并保证不同任务的 `write_paths` 不冲突。唯一 claim 分支只拦截顺序重试和常见旁路,不能替代 dispatcher 的互斥保证。
- 进入评审后 Issue 使用唯一 `status/review`;PR 合并且默认分支任务文件为 `DONE` 后,Issue 才能关闭并标记 `status/done`。
- 领取、结构化 claim 评论、过期锁回收和分支清理的完整规则见 [`../gitea-collaboration.md`](../gitea-collaboration.md)。
@@ -95,4 +96,4 @@ write_paths: # 允许修改的仓库相对路径
- [`../06-tasks.md`](../06-tasks.md):只读路线图(Phase 划分、里程碑、Backlog、建议拆分清单);未启用 Gitea 时以任务文件 frontmatter 为准,启用后以 Issue 为实时状态、合并后的任务文件为长期事实。
- `../../progress.md`:可选工件,用作历史归档或项目级大事记;执行记录写各任务文件,不逐任务追加。
- [`../current-state.md`](../current-state.md):项目级快照(启动/验证路径、目录要点、blocker);任务状态不在此维护,可由脚本汇总 frontmatter 生成。
- [`../gitea-collaboration.md`](../gitea-collaboration.md):启用 Gitea 时的任务映射、原子领取、写路径防撞和 PR 状态协议。
- [`../gitea-collaboration.md`](../gitea-collaboration.md):启用 Gitea 时的任务映射、串行分配、防重复 claim、写路径防撞和 PR 状态协议。