# Progress

## Session Log
- 开始 Analytics 远程公告通道实现：用户确认使用 Cloudflare KV；目标是 Worker/Dashboard/Client 全链路实现 Markdown 公告，客户端与 30 分钟版本检查共用轮询，公告关闭后同 ID 不再显示。
- 文件型计划 catchup 首次使用示例路径失败，实际脚本位于 `~/.config/opencode/.../session-catchup.py`，已重跑成功并记录到计划。
- 已完成 Analytics Worker 和 Dashboard 公告管理改造：Worker 新增公开 `/notice`、管理员 `/api/notice` GET/POST/DELETE；Dashboard 新增公告标题、启用状态、Markdown 内容、读取/发布/停用交互。
- 已完成客户端远程公告接入：`UpdateNotifier` 与版本检查共用 30 分钟定时器，公告使用独立 Dialog 和 Markdown 渲染，关闭后以 `remote_notice_dismissed_id` 记录同 ID 不再显示。
- 已新增 `analytics/scripts/setup-notice-kv.mjs` 和 `analytics/worker` 的 `setup:notice-kv` 脚本，文档补充 KV 创建、公告接口、Dashboard 使用和排查说明。
- 验证进展：`node --check analytics/worker/src/index.js` 和 `node --check analytics/scripts/setup-notice-kv.mjs` 已通过；Dashboard 内嵌脚本首次检查失败是检查命令正则转义问题，准备换字符串索引方式重跑。
- 第一次 `npm run build` 发现 `remoteNotice.ts` 中 `notice.enabled !== false` 在类型收窄后恒为 true，已改为过滤后直接归一 `enabled: true`。
- 复查公告停用流程时发现 `DELETE /api/notice` 需要 CORS 预检支持，已将 Worker `Access-Control-Allow-Methods` 补充 `DELETE`，并重跑 Worker 语法检查通过。
- 远程公告通道验证完成：`node --check analytics/worker/src/index.js`、`node --check analytics/scripts/setup-notice-kv.mjs`、Dashboard 内嵌脚本 `new Function` 检查、`cd client; npm run build`、本轮变更文件 `git diff --check` 均通过；构建仍只有既有 chunk 体积警告，diff check 仍只有 LF/CRLF 提示。
- 用户本地执行 `npm run setup:notice-kv` 失败，原因是本地 Wrangler 没有 `CLOUDFLARE_API_TOKEN` 且脚本以非交互方式调用 Wrangler。已改造为部署前自动幂等执行：优先复用 `NOTICE_STORE_ID`/已配置 id/账号中已有 namespace，不存在才创建；`deploy-if-changed.mjs` 会在 `analytics/worker` 部署前调用该脚本。
- 开始活跃留存与配置使用统计改造：已进入文件型计划，范围限定为客户端配置使用上报、Worker 汇总查询和 Dashboard 展示，不做任务漏斗/错误/耗时统计。
- 已完成客户端埋点接入：`user_config.json` 新增 `analytics_created_at`；`analytics.ts` 支持 `config_usage`；应用启动、设置保存、生图测试、Step02/Step03/Step04 启动会按白名单上报配置枚举值。
- 已完成 Worker 和 Dashboard 改造：Worker 支持 `config_usage`，新增 `/api/retention`、`/api/config-usage`，`summary` 增加活跃/新老客户端；Dashboard 增加活跃指标卡、留存概览、配置使用分布和最近事件分页。
- 验证通过：`node --check analytics/worker/src/index.js`、`node --check client/electron/services/configStore.cjs`、Dashboard 内嵌脚本 `new Function` 语法检查、`cd client; npm run build`、本次改动文件 `git diff --check`。构建仍只有既有 chunk 体积警告，diff check 仍只有 LF/CRLF 提示。
- 已修复代码评审提出的旧匿名客户端 ID 迁移问题：`analytics.ts` 会读取旧 `localStorage.analytics_client_id`，优先用旧 ID 覆盖并保存到 `user_config.json`；当前埋点也直接使用旧 ID。验证通过 `cd client; npm run build` 和 `git diff --check -- client/src/shared/analytics/analytics.ts`。
- 已修复代码评审提出的 `/api/latest` 分页总数采样口径问题：分页 total 改用 `COUNT()`，与 `LIMIT/OFFSET` 明细行数一致，不再用 `SUM(_sample_interval)` 估算事件数。验证通过 `node --check analytics/worker/src/index.js` 和 `git diff --check -- analytics/worker/src/index.js`。
- 已修复线上 `/api/summary`、`/api/retention` 返回 `query failed` 的高风险 SQL：移除 `toDateOrNull/dateDiff/COUNT(DISTINCT IF(...))` 组合，summary 改为多个简单去重查询，retention 改为查询 app_open 明细后在 Worker JS 中计算；查询失败时增加 `console.error`，并在 `analytics/README.md` 补充 `wrangler tail` 查看日志方式。验证通过 `node --check analytics/worker/src/index.js` 和 `git diff --check`。
- 已初始化文件型计划，用于跟踪导入招标文件页面重做任务。
- 已查看客户端导入页、现有文件解析服务、配置存储和工具目录概览，确认需要重做 UI 并重写解析服务分流。
- 已细读 doc2markdown-node、MinerU Agent、MinerU 精准 API demo 的关键流程，下一步迁入/复用解析逻辑。
- 已完成客户端解析链路改造：Electron 文件服务按配置分流本地解析、MinerU-Agent、MinerU 精准 API；导入页改为配置标题 + Markdown 渲染器。
- 已通过 `node -e "require('./electron/services/fileService.cjs'); console.log('file service ok')"`、`node -e "import('./electron/services/doc2markdown/convert.mjs').then(() => console.log('converter ok'))"`、本地 Markdown 转换 smoke test、`npm run build`、`npm audit`。
- 开始技术方案缓存迁移：目标是从 Renderer `localStorage` 改为 Electron Main 侧 `userData` 文件存储，并同步开发说明。
- 已完成技术方案缓存迁移：新增 `workspaceStore.cjs`、`workspaceIpc.cjs`、preload `window.yibiao.workspace`，技术方案 Hook 改为异步读写 Main 侧缓存；`npm run build` 通过。
- 已完成 Step02 招标文件解析：新增解析模式切换、并发流式解析、进度与结果展示，项目概述和技术评分要求成功且进度 100% 后才允许进入目录生成；`npm run build` 通过。
- 已重做 Step02 用户体验：模式选择改为明确的按钮式 Segmented Control，结果展示改为左侧任务列表 + 右侧单项阅读器，不再把所有解析结果铺满页面；`npm run build` 通过。
- 已完成 Step03 目录生成迁移：将旧版后端目录生成 Prompt 与自由/评分项对齐工作流迁入 client service，新增目录生成页面、过程日志、目录树、详情编辑、添加/删除目录项；`npm run build` 通过。
- 已完成 Step02/Step03 后台任务化：新增 Main 侧 `taskService`、`bidAnalysisTask`、`outlineGenerationTask` 和 `tasks:*` IPC/preload，招标文件解析和目录生成切页面不中断，任务状态与结果持续写入 `technical_plan.json`；`npm run build` 和任务模块加载验证通过。
- 已严格对齐后端 `/api/outline/generate-stream` 的目录生成容错机制：client `aiService` 新增 `collectJsonResponse`，目录生成每一步改为 schema 标准化 + validator + JSON 修复 + 最多 3 轮重试；`outlineGenerationTask.cjs` prompt、validator 和工作流已按 backend `OutlineService` 迁移；模块加载、假 AI 流程和 `npm run build` 验证通过。
- 开始 Step04 正文生成与 Word 导出：已确认后端正文生成接口、导出 Word payload、旧前端叶子节点生成逻辑和 client 当前任务/导出占位结构。
- 已新增 Main 侧正文生成任务、任务 IPC/preload 入口、技术方案正文状态类型、Step04 页面主体和 Word 导出服务；首次 CJS 模块验证发现 `??`/`||` 混用语法错误，已改为中间变量修复。
- Step04 正文生成与 Word 导出已完成集成：模块加载验证、Word buffer 生成、假 AI 正文任务流程和 `npm run build` 均通过；构建仍有既有 chunk 体积警告。
- 已核对并修复 Step04 代码评审问题：目录变更时清空正文生成缓存和 outline 节点旧 content；正文 Markdown 渲染移除 `rehypeRaw`，避免模型输出 HTML 被渲染成 DOM；任务模块加载和 `npm run build` 通过。
- 已给正文生成结果增加开头重复章节标题过滤：在 Main 侧流式结果写入工作区前清理独立标题行，覆盖编号标题、Markdown 标题、加粗标题和中文序号标题；针对性用例、假 AI 任务和 `npm run build` 通过。
- 开始 toolbar 拖动与页面内部滚动优化：已进入文件型计划，目标是让底部悬浮工具条可通过手柄拖动，并消除页面全局滚动条。
- 已完成 toolbar 拖动与页面内部滚动优化：`FloatingToolbar` 增加拖动手柄和边界约束；全局布局改为 `100vh` 内部滚动；设置页拆成内部滚动层和悬浮工具条层；移除 toolbar 底部预留空间；`client/开发说明.md` 已补充规则；`npm run build` 和 `git diff --check` 通过。
- 开始 GitHub Release 自动打包与更新检查：目标是 `v*` tag 触发 Windows/macOS 构建，自动生成 Release notes，并在打包客户端启动时检查 GitHub Release 更新。
- 已完成 GitHub Release 自动打包与更新检查：安装 `electron-builder` / `electron-updater`；补齐 `client/package.json` 打包配置；新增 `.github/workflows/release.yml`；新增 `updateService.cjs` 并接入主进程；更新开发说明；`npm run build`、`npm audit`、`updateService` 模块加载、Windows unpacked 和 NSIS 打包验证通过。
- 已修复首次远程发布验证问题：`v2.0.1` Actions 成功但 Release 无产物，是因为正式 Release 与 electron-builder 默认 draft 发布类型冲突；workflow 已改为构建后用 `gh release upload --clobber` 显式上传，同时 Release notes 改为基于 `git log` 生成，并支持手动输入已有 tag 重新发布。
- 已修复 Actions `Build renderer` 的 `TS2688: Cannot find type definition file for 'plist'`：新增 `@types/plist` devDependency，并在 workflow 中补装该类型包以兼容手动重跑旧 tag；`npm run build` 和 `npm audit` 通过。
- 已确认用户此前点击的是旧 run 的 `Re-run all jobs`，不会使用 main 上修复后的 workflow；已通过 `gh workflow run release.yml --ref main -f tag_name=v2.0.1` 触发最新 workflow，`v2.0.1` Release 已成功上传 13 个构建资产并更新提交列表说明。
- 已排查 Windows 安装包“无响应”：下载文件完整且可解包，本地启动后安装器进程有响应窗口；同时已将后续构建产物命名修正为 `Yibiao-版本-平台-架构.ext`，本地 NSIS 构建验证通过。
- 已修复打包后图标仍为 Electron 默认图标：恢复 Windows exe 图标资源编辑；macOS workflow 在打包前从 `assets/icon_256.png` 生成 `assets/icon.icns`；`package.json` 格式、`npm run build` 和 `git diff --check` 通过。
- 已统一 Step02/Step03 左侧进度块为 Step04 的 `content-outline-stats` 风格：Step02 任务列表、Step03 生成日志保持独立滚动；清理旧进度卡样式；`npm run build` 和 `git diff --check` 通过。
- 已将 Step04 Word 导出从手写 XML/浅层 Markdown 正则改为 Markdown AST 到 `docx` 对象模型：支持标题、加粗、斜体、删除线、链接、列表、表格、引用、代码块和图片导出；模块 smoke test、表格/图片 zip 检查、`npm run build`、`npm audit` 和 `git diff --check` 通过。
- 已完成 Step04 正文智能表格与可选配图：设置页新增生图模型状态显示和测试结果持久化；正文生成先做 AI 编排决策，再按决策生成 Markdown 表格和可选图片；生图结果保存到 `workspace/generated-images/` 并以 `yibiao-asset://generated-images/...` 插入正文；预览协议和 Word 导出读取均已支持；模块加载、无生图/有生图 smoke test、`npm run build`、`git diff --check` 通过。
- 已完成 Step04 正文首批体验修正：生成正文落盘前规范 `<br>`，前端正文页启用 raw `<br>` 渲染，Word 导出将 `<br>` 写成真实换行；图例去掉“AI 生成示意”；图片和图例居中；图片支持点击全屏查看；开发者模式下显示配图计划/尝试/成功/失败/跳过统计；`npm run build`、正文任务 smoke test、Word `<br>` 导出 smoke test、`git diff --check` 通过。
- 已完成 Step04 正文第二批优化收尾：mermaid.ink `pako:` 编码改为压缩 JSON 状态；正文任务插入的 Mermaid URL 返回 200 image/png；Word 导出 Mermaid 代码块可嵌入 `word/media/*.png`，且不保留 Mermaid 源代码；mermaid.ink 失败时 Word 导出写入可读占位不崩溃；模块加载、正文任务 smoke test、Word 导出 smoke test、失败路径 smoke test、`npm run build` 和 `git diff --check` 均通过。`npm run build` 仍有既有 chunk 体积警告，`git diff --check` 仍有 LF/CRLF 提示。
- 已完成 Step04 正文第三批优化：安装 `mermaid` 依赖；正文生成中的 Mermaid 改为保存代码块；正文页用 Mermaid 动态导入进行前端本地渲染；Word 导出新增 `export:word-progress` 事件、preload 订阅、Renderer 进度弹窗和核对提示；导出服务返回图片失败 warnings 并写控制台日志，失败时 Word 中保留可读占位。模块加载、正文任务 Mermaid 代码块 smoke test、Word Mermaid 图片导出 smoke test、失败路径 smoke test、`npm run build`、`git diff --check` 均通过。构建新增 Mermaid 动态分包，仍有 chunk 体积警告；`git diff --check` 仍有 LF/CRLF 提示。
- 已修复 Step04 评审问题：正文编排阶段单章节失败会降级为纯正文生成，不再阻断全文任务；Word 导出识别 WebP 并在 Electron 运行时转 PNG；Word 导出补充常见 HTML 节点转换和不支持标签 warning。模块加载、编排失败降级 smoke test、HTML 表格/列表/换行导出 smoke test、WebP Node 失败路径、`npm run build` 和 `git diff --check` 通过。普通 Node 环境无 `nativeImage`，WebP 真正转 PNG 需在 Electron Main 运行时手动复验。
- 已优化 Step04 进度展示：正文任务 stats 增加 `content.phase`、编排总数/完成数和生成总数/完成数；前端在编排阶段优先显示绿色“编排统计”进度条，目录节点从“待生成”改为“编排中”；编排完成后自动切回原有正文生成进度。模块加载、正文任务 stats smoke test、`npm run build` 和 `git diff --check` 通过。
- 已完成 Step04 前端性能优化（不改流式 chunk 节流）：合并正文任务开始/完成/失败处的重复状态事件；`ContentEditPage` 预计算目录节点状态、叶子数和字数，避免渲染目录时反复递归统计；正文 Markdown 渲染拆为 `memo` 组件，只有正文内容变化才重新解析；`TechnicalPlanHome` 使用最新 `event.task` 并把 UI 任务日志裁剪为最近 80 条。模块加载、正文任务事件 smoke test、`npm run build` 和 `git diff --check` 通过。
- 已修复 Step04 全文重新生成行为：点击“重新生成正文”并确认开始后，Renderer 先清空全文正文、章节状态、任务进度并写入工作区缓存；Main 侧收到全文 `regenerate` 时也清空 outline content 和 sections 后再计算初始进度，避免旧内容导致进度仍是 100%。全文重新生成清空 smoke test、`npm run build` 和 `git diff --check` 通过。
- 已完成 Step04 Mermaid 配图渲染失败自修复：正文任务在追加 Mermaid 代码块前先做前端兼容规则和 mermaid.ink 渲染校验；失败后调用文本模型按错误信息最多修复 3 轮；修复通过写入修复后的 Mermaid，连续失败则取消该 Mermaid 配图、保留正文并记录失败统计。模块加载、修复成功 smoke test、连续失败取消 smoke test、`npm run build` 和 `git diff --check` 通过。
- 已完成 Step04 配图阶段重构：编排阶段允许 AI 生图和 Mermaid 双候选；正文生成阶段只保存纯正文；新增 `illustrating` 配图阶段和前端配图进度；配图阶段先按 AI 上限选择 AI 目标，未入选 AI 但有 Mermaid 候选的章节降级为 Mermaid；AI 生图并发 2、Mermaid 校验/修复并发 5，AI 生图失败不自动降级 Mermaid。配图阶段 smoke test、模块加载、`npm run build` 和 `git diff --check` 通过。
- 已修复 Step04 Word 导出表格与编号问题：`parseMarkdown()` 前对 Markdown 表格做导出层归一化，支持标题后紧跟表格和表格行被压成一行的情况；Markdown/HTML 有序列表改为每个列表块独立 numbering reference，避免 Word 跨块连续编号。模块加载、导出 smoke test、`npm run build` 和 `git diff --check` 通过；`git diff --check` 仍只有 LF/CRLF 提示。
- 已完成 Step04 Word 导出压缩表格二次修复：针对截图中的“表头正常、分隔行后拼接数据行”形态，导出前按表头列数拆回 GFM 表格行；截图同形态 smoke test 生成 1 个 Word 表格和 3 行表格行，且不再残留 `:---` 文本。`exportService` 模块加载、`npm run build`、`git diff --check` 通过；构建仍有 Mermaid 相关 chunk 体积警告，`git diff --check` 仍只有 LF/CRLF 提示。
- 已完成 Step04 单章重新生成流程调整：新增 `contentGenerationPlans` 持久化最终编排/配图决策；全文生成后保存每个小节 `ai`/`mermaid`/`none`；单章重新生成优先复用历史编排并跳过编排模型，缺失时只编排目标小节一次，然后重新生成正文并按编排结果重新配图。单章复用与缺失两条 smoke test、正文任务模块加载、`npm run build`、`git diff --check` 通过；`git diff --check` 仍只有 LF/CRLF 提示。
- 已修复 Step04 Word 导出 HTML 容器 P2：`div/section/article` 包含表格、列表、引用、图片等块级子节点时递归导出为 Word 原生结构；纯内联容器仍保持单段落输出；`p` 中出现块级子节点也拆块处理。HTML wrapper smoke test 通过：包裹表格生成 2 个 Word 表格，包裹列表保留 2 个列表项；`exportService` 模块加载、`npm run build`、`git diff --check` 通过，仍只有 LF/CRLF 提示。
- 已修复 Step04 Word 导出列表项内表格问题：Markdown 表格归一化现在会保留空白前缀缩进，并让压缩表格拆出的行继承表头缩进，避免列表内 GFM 表格被破坏。列表项内表格 smoke test 通过：生成 1 个 Word 表格、外围列表保留 2 个列表项，且不残留 `| 备件类别` 或 `:---` 文本；`exportService` 模块加载、`npm run build`、`git diff --check` 通过，仍只有 LF/CRLF 提示。
- 开始知识库完整分析流程重构：已根据用户确认记录完整方案、关键取舍和提示词缓存策略；下一步梳理现有知识库服务、IPC、类型和页面。
- 已梳理现有知识库 Main 服务和 IPC：当前上传后立即 AI 整理并生成 `items.json`，前端没有继续分析入口；需要改为先生成候选条目和 block，再由用户输入批次大小启动匹配。
- 已完成知识库完整流程重构：上传后准备 Markdown、block、筛除日志和两轮候选条目；新增 `startMatching/readAnalysis` IPC/preload/type；前端新增分析调试页和批次输入；匹配阶段按固定全文前缀 + 变量条目批次调用 AI，随后补漏最多两轮并由程序回填正文。
- 验证通过：`node --check electron/services/knowledgeBaseService.cjs`、`node --check electron/ipc/knowledgeBaseIpc.cjs`、`node --check electron/preload.cjs`、知识库 block/filter/prompt smoke test、两次 `npm run build`。`git diff --check` 仅发现非本次修改的 `client/doc/知识库设计.md` EOF 空行和 LF/CRLF 提示。
- 已按反馈优化知识库提示词缓存结构：移除知识库主流程所有 `system` prompt，改为多条 `user` 消息；全文 block 单独作为第一条 user message，任务要求和变量条目放后续 user message。已显式兼容第二轮补充条目返回 `{"items":[]}`，会继续合并首轮条目并进入待匹配。`node --check`、prompt smoke test、`npm run build` 通过。
- 已为知识库流程增加开发者模式详细 JSONL 日志：写入 `userData/logs/knowledge-base/<documentId>.jsonl`，记录文档状态更新、复制/转换、block 筛选统计、每次 AI 调用开始/结束、prompt 消息长度、条目/匹配/补漏数量、保存路径和异常堆栈；分析调试页会展示日志路径。`node --check`、prompt smoke test、`npm run build` 通过。
- 开始 Step03 目录生成弹窗 UI 改造：目标是移除页面原生成方式切换，点击生成目录后在弹窗内选择生成方式和多选参考知识库文档，本轮不改目录生成后台逻辑。
- 已完成 Step03 目录生成弹窗 UI 改造：`OutlineEditPage` 中生成按钮改为打开配置弹窗；弹窗内选择自由生成/按评分项对齐并显示解释；按文件夹列出知识库文档并支持多选完成状态文档；页面顶部移除原生成方式切换。`npm run build` 通过，仍只有既有 chunk 体积警告；`git diff --check` 只有既有 LF/CRLF 提示。
- 已按反馈重做 Step03 弹窗内“参考知识库”交互：改为紧凑搜索框 + 左侧折叠文件夹树 + 右侧已选文档清单；默认只展开第一个有可用文档的文件夹，搜索时自动展开命中结果；默认只展示已完成文档，支持文件夹全选/取消和已选文档移除/清空。`npm run build` 通过，仍只有既有 chunk 体积警告。
- 已完成 Step03 目录生成应用知识库：目录生成 payload 传入参考知识库文档 ID；Main 侧任务服务注入知识库服务；知识库只读返回 `document_id::item_id/title/resume`；目录生成按当前一级目录关键词筛选最多 15 条知识条目，只在二三级目录 prompt 中注入；目录节点只保留合法 `knowledge_item_ids`。已验证对齐模式非法 ID 过滤、自由模式一级目录不使用知识库/二三级使用知识库、CJS 语法检查、`npm run build` 和 `git diff --check`。
- 继续 Step03 知识库目录 Patch 增强：当前 `outlineGenerationTask.cjs` 仍存在旧的章节级知识条目筛选、二三级 prompt 注入和自由模式知识库强制 fallback，需要改为先生成完整目录再全局 Patch。
- 已完成 Step03 知识库目录 Patch 增强：主目录生成不再接收/注入知识库条目，选中文档只在完整目录审核通过后读取轻量条目并调用一次全局 Patch；Patch 只允许 bindings/additions，过滤非法目录/知识 ID，新增节点由程序编号，并全局去重 `knowledge_item_ids`。验证通过：CJS 语法检查、临时 smoke test、`npm run build`、`git diff --check`。
- 已修复 Step03 知识库 Patch 全部过滤问题：Patch prompt 改为真实 ID 示例 + 三类白名单（可绑定目录、可新增父级、可用知识 ID）；Patch 校验改为严格抛错并触发 `collectJsonResponse` 修复，覆盖占位 ID、短 ID、一级绑定、三级 parent、重复知识 ID 等；开发者模式任务日志新增白名单规模、校验失败原因、原始尝试摘要和校验通过统计。修复 smoke test、CJS 语法检查、`npm run build` 和 `git diff --check` 通过。
- 开始 Step03 知识库 additions-only 重构：已确认 `outlineGenerationTask.cjs` 仍保留旧 `bindings/additions + knowledge_item_ids` Patch、严格知识 ID 校验和应用层绑定落盘逻辑；下一步替换为只补缺失三级目录。
- 已完成 Step03 知识库 additions-only 重构：知识库增强 prompt 不再暴露知识库 ID，只输出 `additions[parent_id,title,description]`；normalizer 支持数组/items/directories 归一、删除多余字段、三级 parent 自动上提、description 用 title 补齐和 parent+title 去重；应用层只把新增三级目录追加到现有二级目录并用空知识 ID 集合归一，确保不落 `knowledge_item_ids`。验证通过：临时 smoke test、5 个 CJS `node --check`、`npm run build`、`git diff --check`；构建仍只有既有 chunk 体积警告，diff check 仍只有 LF/CRLF 提示。
- 已完成 Step04 正文编排阶段关联知识库：正文编排 JSON 新增 `knowledge.item_ids`；编排 prompt 在章节动态信息前加入固定知识库轻量清单，只含 `id/title/resume`；Main 侧读取 `reference_knowledge_document_ids` 并复用知识库轻量条目读取；前端启动正文生成时传入当前参考知识库文档 ID；本轮不改正文生成 prompt、不读取知识库正文。验证通过：`node --check electron/services/contentGenerationTask.cjs`、知识库编排归一化 smoke test、`npm run build`、`git diff --check`。`npm run build` 仍只有既有 chunk 体积警告，`git diff --check` 仍只有 LF/CRLF 提示。
- 已完成 Step04 正文生成阶段应用知识库：Main 侧按 `documentId::itemId` 建立知识库正文素材 Map；正文生成时按当前小节 `contentPlan.knowledge.item_ids` 解析对应 `content`，并在正文 prompt 中只注入 content，不传 ID、标题或简介；知识库素材消息放在项目概述之后、章节上下文之前以提升缓存命中可能。验证通过：`node --check electron/services/contentGenerationTask.cjs`、正文 prompt content-only smoke test、`npm run build`、`git diff --check`；构建仍只有既有 chunk 体积警告，diff check 仍只有 LF/CRLF 提示。
- 开始知识库查看链路性能埋点：目标是在开发者模式下记录 `openDocument()` 点击、IPC 读取、返回数据规模、状态更新、条目列表渲染、DOM 提交、Long Task 和下一帧可见，以区分慢点来自读取链路、列表渲染还是单条原文渲染。
- 已完成知识库查看链路性能埋点：新增 `document-items` trace，并让 `document-markdown` trace 从点击开始贯穿 IPC 读取和渲染可见；条目集合会统计总 content 字符数、最大条目、HTML/表格/图片/URL 分布，条目列表也接入 Profiler、DOM 指标、Long Task 和下一帧可见。第一次构建发现 `metrics.chars` 类型推断问题，显式声明为 `Record<string, number>` 后 `cd client; npm run build` 通过，仍只有既有 chunk 体积警告。
- 已将知识库“查看原文”改为弹窗：条目列表不再被原文视图替换，关闭弹窗后保留原滚动位置；弹窗复用现有原文 Markdown 渲染、开发者模式 item-source trace 和一帧延迟渲染逻辑，并新增专用遮罩/卡片/内部滚动样式。验证通过：`cd client; npm run build`，仍只有既有 chunk 体积警告。
- 开始并完成标书查重元数据模块首版：新增 Main 侧 `duplicateCheckService` 和 `duplicate-check:start-metadata-analysis` IPC/preload；Step02 自动启动元数据分析；正文提取与元数据提取并发，内部按文件线性处理；正文提取使用 `preserveImages: true` 并按文件保存 Markdown；元数据页展示两条进度、横向滚动对比表和重复项标红。验证通过：CJS `node --check`、模块加载和 `cd client; npm run build`，构建仍只有既有 chunk 体积警告。
- 已优化标书查重元数据模块：Step02 右上角新增“重新查重”，通过 `force: true` 强制重跑当前文件批次；时间类元数据改为同一天即橙色高亮，不再要求完全一致。验证通过：`node --check electron\services\duplicateCheckService.cjs`、`node --check electron\preload.cjs`、`cd client; npm run build`。
- 已完成标书查重 WPS/DOC/PDF 元数据增强：新增 `cfb` 依赖；`doc2markdown/convert.mjs` 导出 `withLegacyWordDocxFile()`；`.doc/.wps` 读取 OLE `SummaryInformation`、`DocumentSummaryInformation`、自定义属性和 WPS/Kingsoft 痕迹，并尝试转 `.docx` 补充 `docProps`；PDF 展开全部 Info/XMP、fingerprints、permissions 和原始 `/Author` 等记录；动态前缀字段参与横向比较。验证通过：`node --check electron\services\duplicateCheckService.cjs`、转换模块动态 import、查重服务模块加载、`npm run build`、`git diff --check`；`npm audit` 仍报既有 `mermaid` moderate 漏洞，未自动修复。
- 开始标书查重目录分析首版：已确认用户要求纯程序提取目录并比对；招标文件只做句子白名单，投标文件目录项若直接来自招标文件则不计重复；下一步扩展 Main 状态和前端目录 Tab。
- 已完成标书查重目录分析首版：Main 侧基于已提取 Markdown 生成招标句子白名单，按显式目录页/Markdown 标题/语义标题提取投标文件多级目录，命中招标文件句子的目录项不计重复；新增强重复/疑似相似组和文件两两相似度。前端目录 Tab 展示概览、相似度矩阵、文件目录树、重复组和“来自招标文件”灰色标签。验证通过：`node --check electron\services\duplicateCheckService.cjs`、`node --check electron\preload.cjs`、`node --check electron\ipc\duplicateCheckIpc.cjs`、查重服务模块加载、`npm run build`；`git diff --check` 仅本轮文件 LF/CRLF 提示，另有既有 `client/doc/标书查重.md:54 trailing whitespace` 未处理。
- 开始标书查重正文和图片比对：目标是正文按句子用程序聚合重复，招标文件句子作为排除白名单；图片按 hash 找完全相同图片；两个分析在正文 Markdown 提取完成后并发运行，前端用文件编号条和分页列表展示。
- 已完成标书查重正文和图片比对：新增 `contentAnalysis` 和 `imageAnalysis` 工作区状态；正文提取完成后并发运行目录、正文和图片分析。正文比对移除图片后拆句，用招标句子 Set 排除引用内容，再按规范化句子 Map 聚合跨投标文件重复；图片比对解析 Markdown/HTML 图片，读取 `yibiao-asset`/data/file 图片字节并按 SHA256 聚合。前端正文/图片 Tab 已实现投标文件 A/B/C 编号条、重复句子分页和重复图片分页缩略图。验证通过：`node --check electron\services\duplicateCheckService.cjs`、`node --check electron\preload.cjs`、`node --check electron\ipc\duplicateCheckIpc.cjs`、查重服务模块加载、`npm run build`；全量 `git diff --check` 仍有既有 `client/doc/标书查重.md:54 trailing whitespace`，本轮相关文件仅 LF/CRLF 提示。
- 已修复标书查重正文分句的表格拼接问题：正文比对前先提取结构化文本块，HTML 表格按单元格解析，Markdown 管道表按行列解析；移除 `isLikelyMergedTableSentence()` 特例过滤；正文清洗不再删除编号前缀，保留原始标点。真实缓存验证 `无偏离 + 编号 + 下一单元格正文` 异常句为 0，模拟重复分析中表格拼接异常为 0。验证通过：`node --check electron\services\duplicateCheckService.cjs`、`node --check electron\preload.cjs`、`node --check electron\ipc\duplicateCheckIpc.cjs`、查重服务模块加载、真实缓存/Markdown 表格 smoke test、`npm run build`、`git diff --check -- client/electron/services/duplicateCheckService.cjs`。
- 已修复标书查重正文比对忽略句首序号：`normalizeContentSentence()` 现在仅剥离句首结构性序号，展示句仍保留原文；招标引用排除和投标文件重复聚合都会把 `3.特别要求：...` 与 `特别要求：...` 视为同句。真实缓存验证目标句命中招标白名单 5 次且不再进入重复句；`GB/T 29768-2013`、`交货期：30天`、`质保期：3年`、`第2包` 均不被误删。验证通过：CJS 语法检查、preload/IPC 检查、查重服务模块加载、`npm run build`、`git diff --check -- client/electron/services/duplicateCheckService.cjs`。
- 已完成标书查重正文序号归一化二次修复：正文分句改为先生成 `normalized`，再用 `normalized` 判断是否有信息量，避免短标题因句首序号变长而进入重复池；句首结构序号补齐 Markdown 转义 `1\.`、全角数字、括号/圈号后额外分隔符和章节号。真实缓存模拟验证：截图短标题重复项为 0，normalized 句首序号残留为 0，“特别要求”招标引用仍未进入重复结果。验证通过：`node --check electron\services\duplicateCheckService.cjs`、`node --check electron\preload.cjs`、`node --check electron\ipc\duplicateCheckIpc.cjs`、私有函数用例、真实缓存模拟、`git diff --check -- client/electron/services/duplicateCheckService.cjs`、`npm run build`；构建仍只有既有 chunk 体积警告。
