# overflow-fallback（子模块规范）

## 子模块名称

overflow-fallback（溢出与兜底）

## 目标描述

统一定义“无解/溢出”时的行为与返回语义，确保：

- APP 与 WIDGET 在无法覆盖全文时表现一致且可解释
- ELLIPSIS 的字符、清理规则与再次测量约束统一
- SYSTEM_DEFAULT 的返回语义明确（算法层不擅自改变 UI 行为）

## 输入/输出定义

### 输入

- `tokens: Token[]`
- `partialBest?: Layout`（搜索器找到的最佳 partial 或 best effort）
- `overflowMode: 'ELLIPSIS' | 'CLIP' | 'SYSTEM_DEFAULT'`
- `availableWidth: number`
- `maxLines: number`
- `lang: 'TC' | 'EN'`
- `context: 'APP' | 'WIDGET'`
- `ellipsisToken: string`（推荐 `"…"`，必须配置化）
- `measureWidth?: fn`（用于“加省略号后再测量”）

### 输出

- `result: { lines: string[]; wrappedText: string; meta: { fallback_type: 'NONE' | 'RELAX_RULES' | 'SYSTEM_DEFAULT'; overflow_type: 'NONE' | 'ELLIPSIS' | 'CLIP'; reason: string } }`

## 验收标准（可验证）

- **overflow 判定一致**：
  - 搜索无法在 `<=maxLines` 覆盖到结束边界 N，即为 overflow
- **ELLIPSIS 规则一致**：
  - 仅处理最后一行
  - 加省略号后必须再次检查不超宽（必要时回退移除 token 再加省略号）
  - EN 回退单位为整词；TC 回退单位为 grapheme
  - 清理规则：不输出 `"  …"`；不输出 `"，…"/"。…"`（按配置决定是否移除末尾标点再加省略号，但必须固定）
- **SYSTEM_DEFAULT 语义一致**：
  - 仍返回 `lines/wrappedText`
  - 仅在 meta 标记 `fallback_type=SYSTEM_DEFAULT`
  - UI 可依据 meta 决定是否完全交给系统排版
- **确定性**：同输入同输出（含 meta）

## 依赖与关联

- **依赖**：`core-contract`（重组）、`width-measurement`（测量/降级）、`scoring-tiebreak`（避免截断短语的策略可复用评分）
- **被依赖**：`search-engine-app`、`search-engine-widget`、`integration`、`golden-tests`

