6.3 KiB
breakpoint-candidates(任务清单)
对应计划:
spec_kit/Text Wrap/modules/breakpoint-candidates/plan.md状态含义:
[ ]未完成,[x]已完成。
执行完本清单后,需要在spec_kit/overview.md的Text Wrap条目下补充“已完成编码/任务执行完毕”的标记(见最后一节)。
0. 任务标记规则
- 用勾选框标记执行状态:
[ ]未完成[x]已完成
- 每个任务必须可独立验收(有明确产出与检查方式)。
- 所有代码注释必须为简体中文,并把“去重/裁剪/排序/过滤”的确定性口径写死,避免后续模块漂移。
1. 前置对齐(口径必须写死)
-
1.1 明确
pos的边界范围:仅输出pos ∈ [1, N-1]- 原因:
pos=0/N属于搜索器的起止边界,不应作为候选断点 - 验收:单测覆盖
N=0/1/2等边界输入,不会输出非法 pos。
- 原因:
-
1.2 明确
forbiddenBreakRanges的区间口径(写死一种)- 本任务采用:闭区间
start <= pos && pos <= end - 验收:单测能验证闭区间边界命中(start/end 两端都被剔除)。
- 本任务采用:闭区间
2. 目录与代码骨架(客户端侧实现)
-
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.tsindex.ts(统一导出)
- 验收:目录存在,TS 可正常 import(不报路径错误)。
- 产出(建议文件):
-
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. 断点生成(按语言)
-
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]
- 规则:
-
3.2 TC:标点后断点(kind=PUNCT)
- 规则:
- 若
tokens[i].text ∈ tcPunctuations,生成pos=i+1, kind='PUNCT', priority=30
- 若
- 验收:
- tokens=['我','好','累',',','😮💨'] → 包含
pos=4(kind=PUNCT)
- tokens=['我','好','累',',','😮💨'] → 包含
- 规则:
-
3.3 TC:空格后断点(kind=SPACE)
- 规则:
- 若
tokens[i].text === ' ',生成pos=i+1, kind='SPACE', priority=20
- 若
- 验收:构造含空格 tokens,断点生成稳定且不越界。
- 规则:
-
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. 过滤、去重、裁剪与最终排序(必须确定性)
-
4.1 forbiddenBreakRanges 过滤(闭区间)
- 规则:命中任一 range 则剔除该
pos - 验收:range 边界 start/end 都会剔除。
- 规则:命中任一 range 则剔除该
-
4.2 去重:同 pos 只保留一个 breakpoint
- 规则:
- priority 更高者优先
- priority 相同按 kind 固定序:
PUNCT > SPACE > BALANCE > OTHER
- 验收:构造同 pos 多来源候选,结果唯一且确定性。
- 规则:
-
4.3 TC 裁剪:超过
tcMaxCandidateBreaks时截断(确定性排序后截断)- 排序 key(写死):
- priority 降序
- distToIdeal 升序(到最近 idealPos 的距离;无 idealPos 时为大值)
- pos 升序
- 验收:
- 当候选数 > 上限时,finalCount==tcMaxCandidateBreaks
- 截断结果稳定(同输入同输出)
- 排序 key(写死):
-
4.4 最终输出排序:按
pos升序- 验收:无论内部裁剪排序如何,最终输出始终
pos升序。
- 验收:无论内部裁剪排序如何,最终输出始终
-
4.5 meta 输出
- 规则:
originalCount:过滤/去重/裁剪前的候选数量finalCount:最终输出数量pruned = finalCount < originalCount
- 验收:单测断言 meta 与候选数量一致。
- 规则:
5. 单元测试(Vitest)
-
5.1 新建
generateBreakpoints.test.ts,覆盖 EN 基础用例- 验收:pos=[1,2,3] 且升序。
-
5.2 覆盖 TC:PUNCT/SPACE/BALANCE 生成
- 验收:关键样例存在,且 BALANCE 不越界。
-
5.3 覆盖 forbiddenBreakRanges(闭区间)
- 验收:start/end 命中都剔除。
-
5.4 覆盖去重与 kind 优先级
- 验收:同 pos 多候选时输出唯一且正确 kind。
-
5.5 覆盖 TC 裁剪上限与确定性
- 验收:
- 数量上限严格生效
- 同输入多次调用输出完全一致(包括 meta)
- 验收:
6. 最终自检清单(合入前)
-
6.1
npm test通过(包含本模块新增用例)- 验收:不影响现有测试文件。
-
6.2
npx tsc --noEmit通过(或项目既有 TS 检查命令通过)- 验收:无类型错误。
-
6.3 注释与口径自检(简体中文)
- 检查点:
pos边界范围[1,N-1]- forbiddenBreakRanges 闭区间口径
- 去重优先级与裁剪排序 key 的固定顺序
- 验收:后续模块开发者只看代码也不会产生歧义。
- 检查点:
7. 文档回写(任务清单执行完毕后必须做)
- 7.1 在
spec_kit/overview.md的Text Wrap条目下补充执行状态- 建议写法:
- 增加一行:
- **已完成编码(阶段性)**:breakpoint-candidates(候选断点生成与裁剪)
- 增加一行:
- 验收:overview 能反映该子模块已完成,便于全局追踪。
- 建议写法: