docs(07): create phase plan

This commit is contained in:
shen 2026-05-22 20:04:47 +08:00
parent 46fa9fceff
commit 21c8bbb23a
7 changed files with 400 additions and 6 deletions

View File

@ -3,7 +3,7 @@ gsd_state_version: 1.0
milestone: v1.1
milestone_name: WXRead 深化对齐
status: ready_to_execute
last_updated: "2026-05-22T05:54:18.839Z"
last_updated: "2026-05-22T12:03:00.000Z"
last_activity: 2026-05-22
progress:
total_phases: 4
@ -23,12 +23,13 @@ progress:
参见:`.planning/PROJECT.md`(更新于 2026-05-22
**核心价值:** 稳定可用的 EPUB/TXT 阅读体验
**当前关注:** `v1.1` 已完成 Phase 6 规划,下一步进入执行
**当前关注:** `v1.1` 已完成 Phase 6-7 规划,下一步按顺序进入执行或继续规划 Phase 8
## 当前结论(摘要)
- `v1.1` 已基于现有候选需求正式生成 active `REQUIREMENTS.md``ROADMAP.md`
- 当前活跃 roadmap 包含 Phase 6-9页面几何、属性闭环、分页质量/缓存、自动化回归。
- Phase 7 已补齐 research / patterns / validation / plans属性闭环的实现入口已收敛到 renderer → layouter → page metadata 这条链路。
- `v1.0` 归档与 audit 仍保留在 `.planning/milestones/``.planning/v1.0-MILESTONE-AUDIT.md` 供后续追溯。
## 当前风险焦点
@ -50,14 +51,16 @@ progress:
## 下一步
- 建议下一步:`$gsd-discuss-phase 6`
- 建议下一步:`$gsd-execute-phase 6` 或继续 `$gsd-plan-phase 8`
- 已完成的产物目录:
- `.planning/milestones/`
- `.planning/phases/06-page-geometry-and-interaction-hit-layer/`
- `.planning/phases/07-wxread/`
- `.planning/REQUIREMENTS-v1.1-WXRead-next.md`
## Current Position
Phase: 6
Plan: 06-01 / 06-02 / 06-03
Phase: 7
Plan: 07-01 / 07-02 / 07-03
Status: Ready for execute-phase
Last activity: 2026-05-22 — Phase 6 context, research, validation, and plans created
Last activity: 2026-05-22 — Phase 7 research, validation, patterns, and plans created

View File

@ -0,0 +1,75 @@
---
phase: 7
plan: 07-01
type: execute
wave: 1
depends_on: []
files_modified:
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
autonomous: true
requirements:
- ATTR-01
- ATTR-03
---
# Phase 7-01: 自定义分页语义映射
<objective>
定义一套显式的 WXRead 分页语义模型,并把章节 HTML/CSS 中的分页相关语义稳定映射到 attributed string作为后续分页器消费的唯一事实来源。
</objective>
<must_haves>
- `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter`、`pageRelate` 至少在 attributed string 层形成统一属性键闭环。
- 块元素分类需要在 attributed string 或配套语义模型中可读,而不是只存在于 HTML 标签解析时的瞬时判断。
- 现有 `fragmentOffsets`、`pageStartOffset`、`pageEndOffset` 兼容语义不被破坏。
</must_haves>
<tasks>
<task id="07-01-01">
<type>execute</type>
<action>`RDEPUBTextRenderer.swift``RDEPUBReadingModels.swift` 中定义 Phase 7 需要的原生分页语义类型和属性键,例如块类型、分页 hint、附件垂直居中值、页面关联标记等。保持命名收敛避免把语义散落成多个匿名字符串常量。</action>
<read_first>
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
- .planning/phases/07-wxread/07-RESEARCH.md
- Doc/WXRead/analysis/DTCoreText自定义修改分析.md
</read_first>
<acceptance_criteria>
- 新语义有明确的 Swift 类型或受控 raw-value 定义,不依赖匿名 magic string。
- 至少覆盖 `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter`、`pageRelate`、块类型、附件垂直居中语义。
- 现有 `rdPageBlockRange`、`rdPageBlockIndex`、`rdPageAttachmentKind` 语义保持兼容,不被重命名或删除。
</acceptance_criteria>
</task>
<task id="07-01-02">
<type>execute</type>
<action>扩展 `RDEPUBTextRendererSupport``RDEPUBDTCoreTextRenderer` 的 preprocessing / post-processing 流程,从章节 HTML/CSS 中提取上述语义并写入 attributed string。优先复用现有 chapter preprocessing 与 attribute normalization 流程,必要时通过可诊断的桥接标记或受控 HTML 注入把 DTCoreText 默认不会保留的语义带过来。</action>
<read_first>
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift
- ReadViewDemo/Pods/DTCoreText/Core/Source/DTHTMLElement.h
- ReadViewDemo/Pods/DTCoreText/Core/Source/DTHTMLAttributedStringBuilder.m
</read_first>
<acceptance_criteria>
- 渲染后的 attributed string 至少能在对应 range 上读到分页 hint、页面关联标记与块类型中的一部分或全部。
- 无法直接保真的语义必须有明确桥接策略和诊断回退,而不是默默丢失。
- 现有章节渲染流程仍可构建 native text 样本,不引入 fixed/interactive 分支依赖。
</acceptance_criteria>
</task>
</tasks>
<verification>
- Build the `ReadViewDemo` workspace with the `ReadViewDemo` scheme.
- 对一个包含图片和复杂块元素的 native text 样本打印 attributed string 语义摘要,确认关键属性可见。
- 确认 fragment marker 提取和现有章节分页入口仍然工作。
</verification>
<success_criteria>
- Phase 7 的核心语义在 attributed string 层稳定存在。
- 语义提取路径集中在 renderer support而不是散落在 UI 层。
- 后续分页器与诊断路径可以消费统一的语义模型。
</success_criteria>

View File

@ -0,0 +1,77 @@
---
phase: 7
plan: 07-02
type: execute
wave: 2
depends_on:
- 07-01
files_modified:
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
autonomous: true
requirements:
- ATTR-01
- ATTR-02
- ATTR-03
---
# Phase 7-02: 分页器消费与页级元数据接线
<objective>
让 native text 分页器与页级元数据真正消费 Phase 7 的自定义语义,使块分类、附件语义和分页 hint 能影响分页边界决策并保留到 page metadata。
</objective>
<must_haves>
- `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter` 不只是“记录下来”,而是能进入分页边界决策或分页诊断。
- 图片/附件的垂直居中等语义必须被保留到 page metadata 或可消费结构中。
- 块类型需要进入 page/frame 级诊断,使 `table / code / list / blockquote` 能被区分。
</must_haves>
<tasks>
<task id="07-02-01">
<type>execute</type>
<action>扩展 `RDEPUBTextLayouter``RDEPUBTextLayoutFrame`,在现有 attachment boundary / block boundary 逻辑上接入分页 hint处理强制分页前后断点、avoid-break 优先回退,以及附件语义对边界选择的影响。需要同时把命中的规则写进 diagnostics避免变成不可解释的隐式行为。</action>
<read_first>
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift
- .planning/phases/07-wxread/07-RESEARCH.md
</read_first>
<acceptance_criteria>
- 命中的 `pageBreakBefore` / `pageBreakAfter` / `avoidPageBreakInside` 规则会改变 break 决策或至少改变诊断结果,不能完全无效。
- 分页 diagnostics 能说明当前页面为何提前断页、避免断页或跟随附件边界调整。
- 现有 page offset 兼容语义不回归native text 仍能完成章节分页。
</acceptance_criteria>
</task>
<task id="07-02-02">
<type>execute</type>
<action>`RDEPUBTextBookBuilder``RDEPUBReadingModels.swift` 中提升并暴露新的页级语义元数据,包括块类型摘要、附件垂直居中/附件分页语义、强制分页命中信息与复杂块分页诊断。保证 chapter/page 级诊断输出对 Demo 和后续回归可复用。</action>
<read_first>
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift
</read_first>
<acceptance_criteria>
- `RDEPUBTextPageMetadata` 或其配套结构能表达块类型、附件语义和分页 hint 命中摘要。
- `RDEPUBTextChapterPaginationDiagnostic` 能输出至少一组与 Phase 7 语义直接相关的诊断信息。
- 图片/附件语义不会在 attributed string → layouter → page metadata 这条链路中丢失。
</acceptance_criteria>
</task>
</tasks>
<verification>
- Build and run `ReadViewDemo` on the simulator.
- 打开包含图片和复杂块元素的 native reflowable 样本,确认分页完成且 diagnostics 中能看见新语义。
- 对比分页前后 page count、offset 映射与现有 restore/search 路径,确认没有基础回归。
</verification>
<success_criteria>
- 自定义分页语义被分页器实际消费。
- 页级元数据可以解释复杂块和附件的分页行为。
- Phase 8 可以在不重复定义语义的前提下继续优化分页质量与附件规则。
</success_criteria>

View File

@ -0,0 +1,78 @@
---
phase: 7
plan: 07-03
type: execute
wave: 3
depends_on:
- 07-01
- 07-02
files_modified:
- ReadViewDemo/ReadViewDemo/ViewController.swift
- Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
autonomous: true
requirements:
- ATTR-01
- ATTR-02
- ATTR-03
---
# Phase 7-03: 诊断与回归证据标准化
<objective>
把 Phase 7 的自定义属性闭环变成可观测、可复现的 demo 证据,让复杂块、附件语义与分页命中规则能稳定出现在运行时诊断和回归日志中。
</objective>
<must_haves>
- Demo 或运行时日志能报告当前 native text 页面命中的分页语义与块类型摘要。
- 图片/附件语义和复杂块分类在真实样本上可见,不依赖阅读源码才能判断是否生效。
- 回归证据格式应尽量稳定,便于后续 Phase 8 / Phase 9 复用。
</must_haves>
<tasks>
<task id="07-03-01">
<type>execute</type>
<action>`RDEPUBReaderController``RDEPUBTextBookBuilder` 增加统一的 Phase 7 语义诊断摘要接口,输出当前页面或章节的块类型、附件语义、分页 hint 命中与 break reason。要求格式确定性强便于比较不同构建结果。</action>
<read_first>
- Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
- .planning/phases/07-wxread/07-PATTERNS.md
</read_first>
<acceptance_criteria>
- 存在一个可从 native text 路径调用的语义诊断摘要接口或方法。
- 摘要至少包含块类型、附件语义或强制分页命中中的两类以上信息。
- 同一章节在同一构建下重复运行时,摘要格式稳定且可比较。
</acceptance_criteria>
</task>
<task id="07-03-02">
<type>execute</type>
<action>扩展 `ReadViewDemo/ReadViewDemo/ViewController.swift` 的样本验证输出,至少对一个图片/附件章节和一个复杂块章节打印 Phase 7 语义摘要,并保留现有 native/fixed/interactive/TXT 矩阵。必要时补充最小的控制器接线,确保 demo 能暴露这些证据。</action>
<read_first>
- ReadViewDemo/ReadViewDemo/ViewController.swift
- Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift
- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift
- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift
</read_first>
<acceptance_criteria>
- Demo 启动日志或显式诊断输出包含 Phase 7 语义摘要。
- 复杂块与附件样本至少各有一条可读证据,能证明语义没有在链路中丢失。
- 原有 fixed / interactive EPUB 与 TXT 路径仍保留在样本矩阵中,没有被新的 native text 诊断覆盖掉。
</acceptance_criteria>
</task>
</tasks>
<verification>
- Build and launch `ReadViewDemo` in the simulator.
- 记录复杂块样本与图片/附件样本的语义诊断摘要,确认块类型、附件语义、分页 hint 命中可见。
- 重新分页、切换主题或字号后再次记录摘要,确认格式仍稳定且基础导航语义未回归。
</verification>
<success_criteria>
- Phase 7 产出稳定的运行时证据,而不是只留下源码层推断。
- 复杂块、附件语义与分页规则在 demo 中可见。
- 后续阶段可以直接复用这些诊断输出做质量收敛和自动化回归。
</success_criteria>

View File

@ -0,0 +1,36 @@
# Phase 7: WXRead 自定义属性闭环 - Patterns
## Reusable Patterns
### Renderer support 已经是语义收口点
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift` 已负责 HTML 预处理、CSS layer 注入、fragment marker 注入和属性归一化。
- 新的 WXRead 语义应优先在这里被提取、标准化并写成统一属性键,而不是散落到 controller 或 view 层。
### Page metadata 已经是分页结果的公开契约
- `Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift``RDEPUBTextPageMetadata` 已经对外承载 `breakReason`、`blockRange`、`attachmentKinds` 和 `diagnostics`
- 新增块类型、附件垂直居中、强制分页、avoid-break 命中等信息时,应继续沿用这个页级元数据汇总口。
### Layouter 已经掌握分页边界决策
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift` 当前决定 attachment boundary、block boundary 和 frame limit。
- 所有“是否提前断页 / 是否避免截断 / 是否记录强制分页原因”的规则都应该在这里收敛,而不是后置到 UI 层补判断。
### BookBuilder 已经是诊断出口
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` 会把 frame 元数据提升为 chapter/page并产出 chapter 级诊断摘要。
- Phase 7 的复杂块分类与附件语义诊断最适合从这里向 demo 和后续回归路径暴露。
## Closest Existing Analogs
- `rdPageAttachmentKind` 是附件语义的最近现有 analog但只区分 `image/generic`,不够承载 WXRead 风格值。
- `rdPageBlockRange` / `rdPageBlockIndex` 是块级语义的最近现有 analog可以在此基础上继续引入 block kind 与分页 hint。
- `RDEPUBTextChapterPaginationDiagnostic.sampleNotes` 是最接近“可比对证据”的现有出口,适合扩展为 Phase 7 的语义诊断摘要。
## Design Guardrails
- 不直接搬运微信读书私有 DTCoreText 魔改实现;只复用公开文档中可验证的语义与行为目标。
- 继续沿用现有 chapter preprocessing、DTCoreText renderer contract 和 page offset 兼容语义。
- 新属性必须可观测:要么进入 attributed string 属性键,要么进入 page metadata / diagnostics不能只存在于瞬时局部变量。
- 不把 Phase 7 扩展成分页质量全面重写;复杂质量收敛和缓存仍属于 Phase 8。

View File

@ -0,0 +1,46 @@
# Phase 7: WXRead 自定义属性闭环 - Research
**Date:** 2026-05-22
**Phase:** 7
## Research Question
What do we need to know to plan the WXRead custom pagination-attribute closure well for the native text pipeline?
## Current State
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift` 已经负责章节 HTML 预处理、CSS 分层注入、fragment marker 注入,以及 `normalizeReadingAttributes` 的统一属性收口。
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift` 当前只把 DTCoreText 产出的 attributed string 交给通用后处理,没有显式保留 WXRead 风格的分页语义。
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift` 目前只定义了 `rdPageBlockRange`、`rdPageBlockIndex`、`rdPageFragmentID`、`rdPageAttachmentKind` 四个原生属性键,缺少分页控制语义模型。
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift` 已经会消费 block/attachment 元数据,并在分页时输出 `breakReason`、`blockRange`、`attachmentKinds`、`diagnostics`,但还不会消费 `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter`、`pageRelate` 这类显式语义。
- `Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift``RDEPUBTextPageMetadata` 已经是页级元数据汇总点,适合继续承载块类型、附件语义、强制分页、分页诊断摘要。
- `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift` 会把分页结果提升为 chapter/page 模型,并生成诊断摘要,是把新语义暴露给 Demo、回归、后续 Phase 8 的最佳出口。
- `Doc/WXRead/analysis/EPUB渲染管线详解.md``Doc/WXRead/analysis/DTCoreText自定义修改分析.md` 明确给出了目标语义集合:`wr-vertical-center-style`、`weread-page-relate`、`avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter`,以及 `table / code / list / blockquote` 这类块分类。
- `ReadViewDemo/Pods/DTCoreText/Core/Source/DTHTMLElement.*``DTHTMLAttributedStringBuilder.*` 是当前可复用的底层行为边界:现阶段更现实的是在现有 chapter preprocessing 和 attributed-string 后处理层增量接线,而不是直接重写 DTCoreText 私有实现。
## What This Means
1. Phase 7 的缺口不是“再造一个 renderer”而是给现有 renderer 增加一套显式、可诊断、可分页消费的语义模型。
2. 最稳妥的切入点是 `RDEPUBTextRendererSupport`,因为它已经同时掌握 HTML、CSS、attributed string、fragment marker 和统一后处理。
3. 块分类和分页语义必须先在 attributed string 上变成稳定属性键,后面的 layouter / page metadata / demo 诊断才能复用同一份事实。
4. 附件语义不能只保留“是不是图片”,还需要保留像 `wr-vertical-center-style` 这样的消费值,否则 Phase 8 无法继续细化图片/附件规则。
5. `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter` 不能停留在“记录下来”,它们至少要影响分页边界选择或诊断结果,否则闭环是不完整的。
## Recommended Planning Shape
- **Plan 07-01:** 定义语义模型与属性键,把 HTML/CSS 中的分页相关语义稳定映射到 attributed string。
- **Plan 07-02:** 让分页器和页级元数据真正消费这些语义,尤其是块分类、强制分页、附件垂直居中与 avoid-break 规则。
- **Plan 07-03:** 把语义闭环暴露到 demo / 诊断 / 回归路径,确保复杂样本上可观察、可比对、可复现。
## Technical Risks
- 如果语义提取分散在 renderer、layouter、UI 多处Phase 8 会继续面对“同一规则多处解释”的漂移问题。
- DTCoreText 默认产物对自定义 CSS 属性并不天然保真Phase 7 需要在 preprocessing 或 post-processing 层建立明确桥接策略。
- `avoidPageBreakInside` 与强制分页一旦直接改写分页边界,最容易引入 page offset 回归,因此必须把兼容契约和诊断一起规划进去。
- 块分类如果只靠标签名静态猜测,遇到 EPUB 自带 class/style 变体时可能不稳定;计划里需要明确保守策略和可诊断回退。
## Validation Implications
- 现有仓库没有独立测试靶Phase 7 仍需依赖 simulator build/run 与 demo 日志证据。
- 验证重点必须覆盖三类证据:属性是否进入 attributed string、分页器是否消费、demo 是否能看见块类型/附件语义/分页原因。
- 复杂样本至少要覆盖代码块/表格/列表/引用块以及含图片附件章节,否则 ATTR-02 / ATTR-03 的闭环无法证明。

View File

@ -0,0 +1,79 @@
---
phase: 7
slug: wxread
status: draft
nyquist_compliant: true
wave_0_complete: false
created: 2026-05-22
---
# Phase 7 — Validation Strategy
> Per-phase validation contract for WXRead custom pagination-attribute closure.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | none — simulator build/run and manual UAT |
| **Config file** | none |
| **Quick run command** | `xcodebuild -workspace ReadViewDemo/ReadViewDemo.xcworkspace -scheme ReadViewDemo -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 17' build` |
| **Full suite command** | `xcodebuild -workspace ReadViewDemo/ReadViewDemo.xcworkspace -scheme ReadViewDemo -configuration Debug -destination 'platform=iOS Simulator,name=iPhone 17' build && build_run_sim` |
| **Estimated runtime** | ~180 seconds |
---
## Sampling Rate
- After every task commit: run the quick build command.
- After every plan wave: run the full simulator build/run path and confirm the native text sample books still open.
- Before execution handoff: confirm the semantic-attribute and pagination-diagnostic checks below.
- Max feedback latency: 180 seconds.
---
## Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| 07-01-01 | 07-01 | 1 | ATTR-01 | — | N/A | build | `xcodebuild ... build` | ✅ | ⬜ pending |
| 07-01-02 | 07-01 | 1 | ATTR-01 / ATTR-03 | — | N/A | build | `xcodebuild ... build` | ✅ | ⬜ pending |
| 07-02-01 | 07-02 | 2 | ATTR-01 / ATTR-02 | — | N/A | simulator | `build_run_sim` | ✅ | ⬜ pending |
| 07-02-02 | 07-02 | 2 | ATTR-03 | — | N/A | simulator | `build_run_sim` | ✅ | ⬜ pending |
| 07-03-01 | 07-03 | 3 | ATTR-02 / ATTR-03 | — | N/A | manual | simulator inspection | ✅ | ⬜ pending |
| 07-03-02 | 07-03 | 3 | ATTR-01 / ATTR-03 | — | N/A | manual | simulator inspection | ✅ | ⬜ pending |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
---
## Wave 0 Requirements
- Existing build path covers the phase requirements; no new test target is required.
- Demo validation must include at least one native text sample with images/attachments and one sample containing code/list/table/blockquote-like structure.
---
## Manual-Only Verifications
| Behavior | Requirement | Why Manual | Test Instructions |
|----------|-------------|------------|-------------------|
| `avoidPageBreakInside` / `pageBreakBefore` / `pageBreakAfter` 规则能在分页日志或诊断中看见 | ATTR-01 | 需要结合真实章节分页结果,而不是只看源码 | 打开 native text 样本,记录分页摘要,确认强制分页或 avoid-break 命中会出现在诊断输出 |
| 图片/附件垂直居中等语义在 page metadata 或展示侧可见 | ATTR-02 | 需要运行时确认附件语义没有在 attributed string 到分页器之间丢失 | 打开包含图片的章节,检查 demo 日志或调试输出是否显示 attachment semantic / vertical-center 信息 |
| 代码块、表格、列表、引用块分类可区分并进入分页诊断 | ATTR-03 | 这是复杂样本行为,必须在真实内容上确认 | 打开复杂图文章节,确认诊断摘要能区分 block kind并能解释分页边界为何调整 |
---
## Validation Sign-Off
- [ ] All tasks have `<acceptance_criteria>` or manual checks
- [ ] Sampling continuity: no 3 consecutive tasks without a build or simulator check
- [ ] Wave 0 covers missing infrastructure
- [ ] No watch-mode flags
- [ ] Feedback latency < 180s
- [ ] `nyquist_compliant: true` set in frontmatter
**Approval:** pending