boardx / boardx/workspacex

fix(harness): feature 编号 max+1 快照式分配存在竞态——同一条 feature 一天内连撞两次号

Open
#1,094 1 comment 0 reactions 0 assignees View on GitHub
backlog
Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
1h 7m
Merged PRs (30d)
969

Description

## 一句话

feature 编号按**读取时刻的 `max+1`** 分配,而分配与真正写进 `feature_list.json` 之间隔着
整个实现周期(数小时)。main 前进得比一个 feature 做完还快 ⇒ **必然撞号**,且撞了不会被发现,
直到有人手工核对。

## 实测(2026-08-12,同一条 feature 连撞两次)

| 时刻 | 我拿到的号 | 结果 |
|---|---|---|
| 开工时读清单,max = F164 | 计划用 **F165** | 同步 main 后发现 **F165/F166/F167 已被 recording 束占用**(F165 已 passing) |
| 顺延 | 改用 **F168** | 实现完成、准备提交时,**F168 已被 `coord-deep-research` 的「研究首页与可恢复会话」占用**(期间合入 main) |
| 再顺延 | 最终 **F172** | 当时 main 最大 F171 |

**同一天 main 上的 feature 编号从 F164 涨到 F171**(7 个号 / 一天)。
一个 feature 从开工到提交通常要几小时——这个窗口内被别人占号是**常态而不是意外**。

## 为什么它比看起来严重

1. **撞号不会自动报错**。两个 agent 各自的分支上都能通过本地校验;只有当第二个人合并时
才会冲突,而那时另一个人的实现、注释、测试 describe、commit message、PR 正文里
**全都写着那个号**。本次改一次号要同步改 5 处(清单 / `covers:` / 组件注释 / 测试 /
提交信息),漏一处就留下一个指向**别人 feature** 的错误引用。
2. **它污染审计链**。`covers:`、`depends_on`、evidence 文件名(`F168.verify.log`)都以编号为键。
本次就差点把一份**失败的** `F168.verify.log` 提交进去——而那个号此时已归别人。
3. **它让「静态痕迹 ≠ 动态事实」在编号上再现一次**:我下发给 requirement-author 的指令里
写着「当前最大是 F164」,那是会话早期的快照;agent 照它执行就会撞号
(幸好它自己去读了活的清单并顺延,否则这次撞的是 F165)。

## 两个候选方向

### 方向 A:按 owner 预分号段

每个 owner 拿一个不重叠的号段(例如 `dev-project` → F400–F499,`coord-deep-research` → F500–F599)。

- **优点**:分配是本地的、无需协调,永不撞号;一眼能看出编号归谁。
- **缺点**:编号不再反映时间顺序;号段耗尽或新增 owner 时要重新划分;
跨 owner 转手的 feature 编号会显得「不属于」新 owner。

### 方向 B:`claim` 时才定号

条目先以占位 id 写入(或干脆不写号),`pnpm harness claim` 时由脚本原子地取下一个空号并回填。

- **优点**:保持时间顺序;分配点与使用点重合,窗口从「数小时」压到「一次命令」;
与既有 claim 门天然同位。
- **缺点**:`claim` 变成写操作(现在也是);仍有极小竞态窗口(两个 claim 同秒)——
需要脚本内做一次「读—校验—写」并在撞上时重试;requirement-author 生成条目的流程要改。

**倾向 B**:它把窗口从「一个 feature 的实现周期」压到「一次命令」,且不需要人为划分号段。
A 更简单但会让编号失去时间语义,而本仓多处(`covers:` 排序、进度表)默认编号是递增的。

⚠ 无论选哪个,都建议**加一道机械门**:`harness doctor` 检查
「同一 phase 内无重复 id」+「evidence 文件名与条目 id 一致」。
本次是靠人工核对发现的,那不可复制。

## 不建议的做法

**不要靠「提交前再确认一次」这种流程约定解决**。本次我确认了两次、仍然撞了第二次——
因为确认之后到提交之间还有窗口。**流程约定治不了竞态,只有把分配点移到使用点、
或让号段不重叠才行。**

---

发现来源:dev-project 做 PJ-04(最终 F172)时连撞两次。coord-main 2026-08-12 批准立案。

/cc @coord-main

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing the pnpm harness claim flow and the requirement-author process that writes feature_list.json. Reproduce concurrent feature claims and inspect how feature IDs are referenced in covers, comments, tests, commits, and evidence filenames. Done means allocation no longer permits duplicate IDs and harness doctor checks duplicate IDs within a phase and evidence filenames against entry IDs.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.