# breakpoint-candidates（任务清单）

> 对应计划：`spec_kit/Text Wrap/modules/breakpoint-candidates/plan.md`
>
> 状态含义：`[ ]` 未完成，`[x]` 已完成。  
> 执行完本清单后，需要在 `spec_kit/overview.md` 的 `Text Wrap` 条目下补充“已完成编码/任务执行完毕”的标记（见最后一节）。

---

## 0. 任务标记规则

- 用勾选框标记执行状态：
  - `[ ]` 未完成
  - `[x]` 已完成
- 每个任务必须可独立验收（有明确产出与检查方式）。
- 所有代码注释必须为简体中文，并把“去重/裁剪/排序/过滤”的**确定性口径**写死，避免后续模块漂移。

---

## 1. 前置对齐（口径必须写死）

- [x] 1.1 明确 `pos` 的边界范围：仅输出 `pos ∈ [1, N-1]`  
  - **原因**：`pos=0/N` 属于搜索器的起止边界，不应作为候选断点  
  - **验收**：单测覆盖 `N=0/1/2` 等边界输入，不会输出非法 pos。

- [x] 1.2 明确 `forbiddenBreakRanges` 的区间口径（写死一种）  
  - **本任务采用**：闭区间 `start <= pos && pos <= end`  
  - **验收**：单测能验证闭区间边界命中（start/end 两端都被剔除）。

---

## 2. 目录与代码骨架（客户端侧实现）

- [x] 2.1 新建目录 `client/src/features/textWrap/breakpoints/`  
  - **产出**（建议文件）：
    - `types.ts`（Breakpoint/Config/Constraints）
    - `generateBreakpoints.ts`（主入口，纯函数）
    - `tcCandidates.ts`（TC：PUNCT/SPACE/BALANCE 生成）
    - `enCandidates.ts`（EN：SPACE 断点生成）
    - `filterAndDedup.ts`（过滤/去重/排序/裁剪）
    - `__tests__/generateBreakpoints.test.ts`
    - `index.ts`（统一导出）
  - **验收**：目录存在，TS 可正常 import（不报路径错误）。

- [x] 2.2 定义最小类型集合（只覆盖本模块）  
  - **必须包含**：
    - `Breakpoint = { pos: number; kind: 'PUNCT'|'SPACE'|'BALANCE'|'OTHER'; priority: number }`
    - `BreakpointMeta = { pruned: boolean; originalCount: number; finalCount: number }`
    - `Constraints = { forbiddenBreakRanges?: Array<{ start: number; end: number }>; protectedPhrases?: string[] }`
    - `Config = { tcMaxCandidateBreaks: number; tcPunctuations: string[]; balanceRange: number }`
  - **验收**：后续实现文件引用类型清晰，且不会引入无关依赖。

---

## 3. 断点生成（按语言）

- [x] 3.1 EN 候选断点生成（kind=SPACE，priority 固定）  
  - **规则**：
    - 对 `i in 1..N-1` 生成 `pos=i, kind='SPACE'`
    - `priority=10`（写死）
  - **验收**：
    - tokens=[I, am, so, tired] → pos=[1,2,3]

- [x] 3.2 TC：标点后断点（kind=PUNCT）  
  - **规则**：
    - 若 `tokens[i].text ∈ tcPunctuations`，生成 `pos=i+1, kind='PUNCT', priority=30`
  - **验收**：
    - tokens=['我','好','累','，','😮‍💨'] → 包含 `pos=4(kind=PUNCT)`

- [x] 3.3 TC：空格后断点（kind=SPACE）  
  - **规则**：
    - 若 `tokens[i].text === ' '`，生成 `pos=i+1, kind='SPACE', priority=20`
  - **验收**：构造含空格 tokens，断点生成稳定且不越界。

- [x] 3.4 TC：BALANCE 断点生成（kind=BALANCE）  
  - **规则**：
    - `targetLines = min(maxLines, N)`
    - 对 `lineIndex in 1..targetLines-1`：
      - `idealPos = round((N * lineIndex) / targetLines)`
      - 在 `[idealPos-balanceRange, idealPos+balanceRange]` 内生成 pos（裁剪到 `[1,N-1]`）
    - `priority=5`
  - **验收**：
    - 无标点长文本：可生成接近理想位置的候选断点（数量受控、确定性）。

---

## 4. 过滤、去重、裁剪与最终排序（必须确定性）

- [x] 4.1 forbiddenBreakRanges 过滤（闭区间）  
  - **规则**：命中任一 range 则剔除该 `pos`
  - **验收**：range 边界 start/end 都会剔除。

- [x] 4.2 去重：同 pos 只保留一个 breakpoint  
  - **规则**：
    - priority 更高者优先
    - priority 相同按 kind 固定序：`PUNCT > SPACE > BALANCE > OTHER`
  - **验收**：构造同 pos 多来源候选，结果唯一且确定性。

- [x] 4.3 TC 裁剪：超过 `tcMaxCandidateBreaks` 时截断（确定性排序后截断）  
  - **排序 key（写死）**：
    - priority 降序
    - distToIdeal 升序（到最近 idealPos 的距离；无 idealPos 时为大值）
    - pos 升序
  - **验收**：
    - 当候选数 > 上限时，finalCount==tcMaxCandidateBreaks
    - 截断结果稳定（同输入同输出）

- [x] 4.4 最终输出排序：按 `pos` 升序  
  - **验收**：无论内部裁剪排序如何，最终输出始终 `pos` 升序。

- [x] 4.5 meta 输出  
  - **规则**：
    - `originalCount`：过滤/去重/裁剪前的候选数量
    - `finalCount`：最终输出数量
    - `pruned = finalCount < originalCount`
  - **验收**：单测断言 meta 与候选数量一致。

---

## 5. 单元测试（Vitest）

- [x] 5.1 新建 `generateBreakpoints.test.ts`，覆盖 EN 基础用例  
  - **验收**：pos=[1,2,3] 且升序。

- [x] 5.2 覆盖 TC：PUNCT/SPACE/BALANCE 生成  
  - **验收**：关键样例存在，且 BALANCE 不越界。

- [x] 5.3 覆盖 forbiddenBreakRanges（闭区间）  
  - **验收**：start/end 命中都剔除。

- [x] 5.4 覆盖去重与 kind 优先级  
  - **验收**：同 pos 多候选时输出唯一且正确 kind。

- [x] 5.5 覆盖 TC 裁剪上限与确定性  
  - **验收**：
    - 数量上限严格生效
    - 同输入多次调用输出完全一致（包括 meta）

---

## 6. 最终自检清单（合入前）

- [x] 6.1 `npm test` 通过（包含本模块新增用例）  
  - **验收**：不影响现有测试文件。

- [x] 6.2 `npx tsc --noEmit` 通过（或项目既有 TS 检查命令通过）  
  - **验收**：无类型错误。

- [x] 6.3 注释与口径自检（简体中文）  
  - **检查点**：
    - `pos` 边界范围 `[1,N-1]`
    - forbiddenBreakRanges 闭区间口径
    - 去重优先级与裁剪排序 key 的固定顺序
  - **验收**：后续模块开发者只看代码也不会产生歧义。

---

## 7. 文档回写（任务清单执行完毕后必须做）

- [x] 7.1 在 `spec_kit/overview.md` 的 `Text Wrap` 条目下补充执行状态  
  - **建议写法**：
    - 增加一行：`- **已完成编码（阶段性）**：breakpoint-candidates（候选断点生成与裁剪）`
  - **验收**：overview 能反映该子模块已完成，便于全局追踪。

