From 21c8bbb23ae987b1d1587d2fc1354ef3720f6686 Mon Sep 17 00:00:00 2001 From: shen <> Date: Fri, 22 May 2026 20:04:47 +0800 Subject: [PATCH] docs(07): create phase plan --- .planning/STATE.md | 15 ++-- .planning/phases/07-wxread/07-01-PLAN.md | 75 +++++++++++++++++++ .planning/phases/07-wxread/07-02-PLAN.md | 77 ++++++++++++++++++++ .planning/phases/07-wxread/07-03-PLAN.md | 78 ++++++++++++++++++++ .planning/phases/07-wxread/07-PATTERNS.md | 36 ++++++++++ .planning/phases/07-wxread/07-RESEARCH.md | 46 ++++++++++++ .planning/phases/07-wxread/07-VALIDATION.md | 79 +++++++++++++++++++++ 7 files changed, 400 insertions(+), 6 deletions(-) create mode 100644 .planning/phases/07-wxread/07-01-PLAN.md create mode 100644 .planning/phases/07-wxread/07-02-PLAN.md create mode 100644 .planning/phases/07-wxread/07-03-PLAN.md create mode 100644 .planning/phases/07-wxread/07-PATTERNS.md create mode 100644 .planning/phases/07-wxread/07-RESEARCH.md create mode 100644 .planning/phases/07-wxread/07-VALIDATION.md diff --git a/.planning/STATE.md b/.planning/STATE.md index e8b07a6..e21eb33 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -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 diff --git a/.planning/phases/07-wxread/07-01-PLAN.md b/.planning/phases/07-wxread/07-01-PLAN.md new file mode 100644 index 0000000..81277fa --- /dev/null +++ b/.planning/phases/07-wxread/07-01-PLAN.md @@ -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: 自定义分页语义映射 + + +定义一套显式的 WXRead 分页语义模型,并把章节 HTML/CSS 中的分页相关语义稳定映射到 attributed string,作为后续分页器消费的唯一事实来源。 + + + +- `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter`、`pageRelate` 至少在 attributed string 层形成统一属性键闭环。 +- 块元素分类需要在 attributed string 或配套语义模型中可读,而不是只存在于 HTML 标签解析时的瞬时判断。 +- 现有 `fragmentOffsets`、`pageStartOffset`、`pageEndOffset` 兼容语义不被破坏。 + + + + +execute +在 `RDEPUBTextRenderer.swift` 与 `RDEPUBReadingModels.swift` 中定义 Phase 7 需要的原生分页语义类型和属性键,例如块类型、分页 hint、附件垂直居中值、页面关联标记等。保持命名收敛,避免把语义散落成多个匿名字符串常量。 + +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRenderer.swift +- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift +- .planning/phases/07-wxread/07-RESEARCH.md +- Doc/WXRead/analysis/DTCoreText自定义修改分析.md + + +- 新语义有明确的 Swift 类型或受控 raw-value 定义,不依赖匿名 magic string。 +- 至少覆盖 `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter`、`pageRelate`、块类型、附件垂直居中语义。 +- 现有 `rdPageBlockRange`、`rdPageBlockIndex`、`rdPageAttachmentKind` 语义保持兼容,不被重命名或删除。 + + + + +execute +扩展 `RDEPUBTextRendererSupport` 与 `RDEPUBDTCoreTextRenderer` 的 preprocessing / post-processing 流程,从章节 HTML/CSS 中提取上述语义并写入 attributed string。优先复用现有 chapter preprocessing 与 attribute normalization 流程,必要时通过可诊断的桥接标记或受控 HTML 注入把 DTCoreText 默认不会保留的语义带过来。 + +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift +- ReadViewDemo/Pods/DTCoreText/Core/Source/DTHTMLElement.h +- ReadViewDemo/Pods/DTCoreText/Core/Source/DTHTMLAttributedStringBuilder.m + + +- 渲染后的 attributed string 至少能在对应 range 上读到分页 hint、页面关联标记与块类型中的一部分或全部。 +- 无法直接保真的语义必须有明确桥接策略和诊断回退,而不是默默丢失。 +- 现有章节渲染流程仍可构建 native text 样本,不引入 fixed/interactive 分支依赖。 + + + + + +- Build the `ReadViewDemo` workspace with the `ReadViewDemo` scheme. +- 对一个包含图片和复杂块元素的 native text 样本打印 attributed string 语义摘要,确认关键属性可见。 +- 确认 fragment marker 提取和现有章节分页入口仍然工作。 + + + +- Phase 7 的核心语义在 attributed string 层稳定存在。 +- 语义提取路径集中在 renderer support,而不是散落在 UI 层。 +- 后续分页器与诊断路径可以消费统一的语义模型。 + + diff --git a/.planning/phases/07-wxread/07-02-PLAN.md b/.planning/phases/07-wxread/07-02-PLAN.md new file mode 100644 index 0000000..6aa8f64 --- /dev/null +++ b/.planning/phases/07-wxread/07-02-PLAN.md @@ -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: 分页器消费与页级元数据接线 + + +让 native text 分页器与页级元数据真正消费 Phase 7 的自定义语义,使块分类、附件语义和分页 hint 能影响分页边界决策并保留到 page metadata。 + + + +- `avoidPageBreakInside`、`pageBreakBefore`、`pageBreakAfter` 不只是“记录下来”,而是能进入分页边界决策或分页诊断。 +- 图片/附件的垂直居中等语义必须被保留到 page metadata 或可消费结构中。 +- 块类型需要进入 page/frame 级诊断,使 `table / code / list / blockquote` 能被区分。 + + + + +execute +扩展 `RDEPUBTextLayouter` 与 `RDEPUBTextLayoutFrame`,在现有 attachment boundary / block boundary 逻辑上接入分页 hint:处理强制分页前后断点、avoid-break 优先回退,以及附件语义对边界选择的影响。需要同时把命中的规则写进 diagnostics,避免变成不可解释的隐式行为。 + +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift +- .planning/phases/07-wxread/07-RESEARCH.md + + +- 命中的 `pageBreakBefore` / `pageBreakAfter` / `avoidPageBreakInside` 规则会改变 break 决策或至少改变诊断结果,不能完全无效。 +- 分页 diagnostics 能说明当前页面为何提前断页、避免断页或跟随附件边界调整。 +- 现有 page offset 兼容语义不回归,native text 仍能完成章节分页。 + + + + +execute +在 `RDEPUBTextBookBuilder` 与 `RDEPUBReadingModels.swift` 中提升并暴露新的页级语义元数据,包括块类型摘要、附件垂直居中/附件分页语义、强制分页命中信息与复杂块分页诊断。保证 chapter/page 级诊断输出对 Demo 和后续回归可复用。 + +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift +- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayoutFrame.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextLayouter.swift + + +- `RDEPUBTextPageMetadata` 或其配套结构能表达块类型、附件语义和分页 hint 命中摘要。 +- `RDEPUBTextChapterPaginationDiagnostic` 能输出至少一组与 Phase 7 语义直接相关的诊断信息。 +- 图片/附件语义不会在 attributed string → layouter → page metadata 这条链路中丢失。 + + + + + +- Build and run `ReadViewDemo` on the simulator. +- 打开包含图片和复杂块元素的 native reflowable 样本,确认分页完成且 diagnostics 中能看见新语义。 +- 对比分页前后 page count、offset 映射与现有 restore/search 路径,确认没有基础回归。 + + + +- 自定义分页语义被分页器实际消费。 +- 页级元数据可以解释复杂块和附件的分页行为。 +- Phase 8 可以在不重复定义语义的前提下继续优化分页质量与附件规则。 + + diff --git a/.planning/phases/07-wxread/07-03-PLAN.md b/.planning/phases/07-wxread/07-03-PLAN.md new file mode 100644 index 0000000..9bb01ef --- /dev/null +++ b/.planning/phases/07-wxread/07-03-PLAN.md @@ -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: 诊断与回归证据标准化 + + +把 Phase 7 的自定义属性闭环变成可观测、可复现的 demo 证据,让复杂块、附件语义与分页命中规则能稳定出现在运行时诊断和回归日志中。 + + + +- Demo 或运行时日志能报告当前 native text 页面命中的分页语义与块类型摘要。 +- 图片/附件语义和复杂块分类在真实样本上可见,不依赖阅读源码才能判断是否生效。 +- 回归证据格式应尽量稳定,便于后续 Phase 8 / Phase 9 复用。 + + + + +execute +为 `RDEPUBReaderController` 或 `RDEPUBTextBookBuilder` 增加统一的 Phase 7 语义诊断摘要接口,输出当前页面或章节的块类型、附件语义、分页 hint 命中与 break reason。要求格式确定性强,便于比较不同构建结果。 + +- Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift +- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift +- .planning/phases/07-wxread/07-PATTERNS.md + + +- 存在一个可从 native text 路径调用的语义诊断摘要接口或方法。 +- 摘要至少包含块类型、附件语义或强制分页命中中的两类以上信息。 +- 同一章节在同一构建下重复运行时,摘要格式稳定且可比较。 + + + + +execute +扩展 `ReadViewDemo/ReadViewDemo/ViewController.swift` 的样本验证输出,至少对一个图片/附件章节和一个复杂块章节打印 Phase 7 语义摘要,并保留现有 native/fixed/interactive/TXT 矩阵。必要时补充最小的控制器接线,确保 demo 能暴露这些证据。 + +- ReadViewDemo/ReadViewDemo/ViewController.swift +- Sources/RDReaderView/EPUBUI/RDEPUBReaderController.swift +- Sources/RDReaderView/EPUBTextRendering/RDEPUBTextBookBuilder.swift +- Sources/RDReaderView/EPUBCore/RDEPUBReadingModels.swift + + +- Demo 启动日志或显式诊断输出包含 Phase 7 语义摘要。 +- 复杂块与附件样本至少各有一条可读证据,能证明语义没有在链路中丢失。 +- 原有 fixed / interactive EPUB 与 TXT 路径仍保留在样本矩阵中,没有被新的 native text 诊断覆盖掉。 + + + + + +- Build and launch `ReadViewDemo` in the simulator. +- 记录复杂块样本与图片/附件样本的语义诊断摘要,确认块类型、附件语义、分页 hint 命中可见。 +- 重新分页、切换主题或字号后再次记录摘要,确认格式仍稳定且基础导航语义未回归。 + + + +- Phase 7 产出稳定的运行时证据,而不是只留下源码层推断。 +- 复杂块、附件语义与分页规则在 demo 中可见。 +- 后续阶段可以直接复用这些诊断输出做质量收敛和自动化回归。 + + diff --git a/.planning/phases/07-wxread/07-PATTERNS.md b/.planning/phases/07-wxread/07-PATTERNS.md new file mode 100644 index 0000000..15d9f99 --- /dev/null +++ b/.planning/phases/07-wxread/07-PATTERNS.md @@ -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。 diff --git a/.planning/phases/07-wxread/07-RESEARCH.md b/.planning/phases/07-wxread/07-RESEARCH.md new file mode 100644 index 0000000..eacb6c4 --- /dev/null +++ b/.planning/phases/07-wxread/07-RESEARCH.md @@ -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 的闭环无法证明。 diff --git a/.planning/phases/07-wxread/07-VALIDATION.md b/.planning/phases/07-wxread/07-VALIDATION.md new file mode 100644 index 0000000..0be2ad8 --- /dev/null +++ b/.planning/phases/07-wxread/07-VALIDATION.md @@ -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 `` 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 +