From f85dbecf9366e6d3f1c8766df90569272769065c Mon Sep 17 00:00:00 2001 From: QiuSW <105186638@qq.com> Date: Tue, 4 Aug 2026 15:05:33 +0800 Subject: [PATCH] chore(governance): add waiting task status --- docs/00-ai-start-here.md | 2 +- docs/current-state.md | 2 +- docs/gitea-collaboration.md | 7 ++++--- scripts/audit_gitea_coordination.py | 5 +++-- scripts/setup_gitea_labels.py | 6 ++++++ tests/test_governance.py | 8 ++++++++ 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/docs/00-ai-start-here.md b/docs/00-ai-start-here.md index 9a814f4..23c285c 100644 --- a/docs/00-ai-start-here.md +++ b/docs/00-ai-start-here.md @@ -52,7 +52,7 @@ MVP 以默认 16 路跑通一个场景的端到端闭环;架构、数据和 UI ## 任务领取与状态 -- Gitea Issue 是实时状态权威,状态标签为 `status/todo`、`status/doing`、`status/blocked`、`status/review`、`status/done`。 +- Gitea Issue 是实时状态权威,状态标签为 `status/waiting`、`status/todo`、`status/doing`、`status/blocked`、`status/review`、`status/done`;`waiting` 表示尚未领取且因依赖或外部条件不可领取。 - 任务文件保存不可变规格、依赖、写路径、验证门禁和执行证据。 - 一个 agent 同时最多一个活跃任务;一个任务同时只有一个写入者。 - dispatcher 创建 `claims/T-<编号>` 和 `agent//T-<编号>` 后,worker 必须读回确认。 diff --git a/docs/current-state.md b/docs/current-state.md index 954636f..40185a5 100644 --- a/docs/current-state.md +++ b/docs/current-state.md @@ -14,7 +14,7 @@ - `docs/raw/01`~`08` 已记录需求、分析、方案、客户场景、事件比对和三系统职责。 - `docs/raw/contracts/event-v0.1.schema.json` 已冻结,并有多份示例与语义说明。 - harness coding 文档、上下文清单、Gitea Issue/PR 模板和治理脚本已接入。 -- Gitea 已初始化 11 个协作标签;首批 Issue 已建立,实时可领取状态必须从 Gitea 查询,不在本文复制。 +- Gitea 已初始化 12 个协作标签;`status/waiting` 用于依赖或外部条件未满足的未领取任务,实时可领取状态必须从 Gitea 查询,不在本文复制。 - T-002 已关闭架构影响型问题:首期 S2 民办寄宿学校、客户侧私有部署、ONVIF/RTSP、NVIDIA 主路径、自研 Bell、Web/H5 与客户侧证据存储等边界已批准。 - T-004 的 Sense/Bell 单文件交互原型已获产品确认;T-005 已归档 Claude 原稿并补录缺失评审文档,当前定稿与原始依据分开保存。 - `_reference/mibeenvr` 为本地只读参考仓库,已被忽略;只允许 M0 实验与白名单借鉴。 diff --git a/docs/gitea-collaboration.md b/docs/gitea-collaboration.md index fbb156b..7face73 100644 --- a/docs/gitea-collaboration.md +++ b/docs/gitea-collaboration.md @@ -19,7 +19,7 @@ 推荐标签: - 类型:`kind/task` 标识可执行任务,并从 `type/docs`、`type/code` 中选择一个主要变更类型。 -- 状态:`status/todo`、`status/doing`、`status/blocked`、`status/review`、`status/done`。 +- 状态:`status/waiting`、`status/todo`、`status/doing`、`status/blocked`、`status/review`、`status/done`。 - 优先级:`priority/p0`、`priority/p1`、`priority/p2`。 `status/*`、`type/*`、`priority/*` 分别使用 Gitea exclusive scoped labels,同一分组任一时刻最多一个;`kind/task` 为普通标签。 @@ -28,6 +28,7 @@ | 阶段 | 任务文件 | Issue | 分支 / PR | | --- | --- | --- | --- | +| 等待条件 | `TODO` | open + `status/waiting` | 无 claim;依赖或外部条件满足后由 dispatcher 转为 todo | | 待领取 | `TODO` | open + `status/todo` | 无 claim 分支 | | 开发中 | 工作分支上 `DOING` | open + `status/doing` | claim 与工作分支存在 | | 阻塞 | `BLOCKED` | open + `status/blocked` | 默认保留 claim,避免误领 | @@ -40,9 +41,9 @@ Issue 是实时状态权威;默认分支尚未合入工作提交时,其任 1. 先创建任务文件,写清规格、依赖和初始 `write_paths`,合入默认分支;此时 `issue`、`context_ref`、claim / 工作分支均为 `null`。 2. 用 Issue 模板创建唯一主 Issue。新 Issue 只有 `kind/task`,尚未带 `status/todo`。 -3. 把 Issue 编号回填任务文件,并让 Issue 链接该文件;映射提交合入默认分支后,再选择 `type/*`、`priority/*` 和 `status/todo`。 +3. 把 Issue 编号回填任务文件,并让 Issue 链接该文件;映射提交合入默认分支后,再选择 `type/*`、`priority/*`。依赖已全部 `DONE` 且未被人工暂缓时使用 `status/todo`,否则使用 `status/waiting`。 -因此 dispatcher 能从默认分支可靠定位任务 ↔ Issue;没有双向映射或没有 `status/todo` 的任务都不可领取。 +因此 dispatcher 能从默认分支可靠定位任务 ↔ Issue;没有双向映射或不是 `status/todo` 的任务都不可领取。`status/waiting` 不占用 claim,恢复条件必须写在 Issue 评论或任务执行记录中。 ## 串行分配与防重复领取 diff --git a/scripts/audit_gitea_coordination.py b/scripts/audit_gitea_coordination.py index ae8ed93..b62689e 100644 --- a/scripts/audit_gitea_coordination.py +++ b/scripts/audit_gitea_coordination.py @@ -26,6 +26,7 @@ from validate_harness_governance import ( STATUS_LABELS = { "status/todo", + "status/waiting", "status/doing", "status/blocked", "status/review", @@ -558,8 +559,8 @@ def audit_repository( findings.append(AuditFinding(number, "stale", "claim 租期不得超过 24 小时。")) if task.lease_until <= now: findings.append(AuditFinding(number, "stale", "claim 已过期,需人工审查回收。")) - elif status == "status/todo" and claim_branch in branches: - findings.append(AuditFinding(number, "claim", "TODO 仍存在 claim 分支。")) + elif status in {"status/todo", "status/waiting"} and claim_branch in branches: + findings.append(AuditFinding(number, "claim", "未领取状态仍存在 claim 分支。")) matching_prs = [ pr diff --git a/scripts/setup_gitea_labels.py b/scripts/setup_gitea_labels.py index 8d54c3b..66b55f6 100644 --- a/scripts/setup_gitea_labels.py +++ b/scripts/setup_gitea_labels.py @@ -38,6 +38,12 @@ LABELS: tuple[dict[str, Any], ...] = ( "description": "Ready to claim", "exclusive": True, }, + { + "name": "status/waiting", + "color": "D4C5F9", + "description": "Not claimable; waiting on dependency or external condition", + "exclusive": True, + }, { "name": "status/doing", "color": "FBCA04", diff --git a/tests/test_governance.py b/tests/test_governance.py index f41ec73..3cdb9fe 100644 --- a/tests/test_governance.py +++ b/tests/test_governance.py @@ -14,6 +14,9 @@ if str(SCRIPTS) not in sys.path: sys.path.insert(0, str(SCRIPTS)) from audit_gitea_coordination import ( + ACTIVE_LABELS, + READY_OR_ACTIVE_LABELS, + STATUS_LABELS, audit_repository, latest_claim, paged, @@ -177,6 +180,11 @@ class OfflineRuleTests(unittest.TestCase): class GiteaHelperTests(unittest.TestCase): + def test_waiting_status_is_not_claimable_or_active(self) -> None: + self.assertIn("status/waiting", STATUS_LABELS) + self.assertNotIn("status/waiting", READY_OR_ACTIVE_LABELS) + self.assertNotIn("status/waiting", ACTIVE_LABELS) + def test_label_plan_detects_exclusive_change(self) -> None: desired = next(label for label in LABELS if label["name"] == "status/todo") existing = {