From 1771fb48a9c352bae321c309bbe320dba76434de Mon Sep 17 00:00:00 2001 From: DDT <––1786035110@stu.gpnu.edu.cn> Date: Sun, 23 Aug 2026 20:16:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E9=98=B6=E6=AE=B5=E4=BA=94?= =?UTF-8?q?=E5=87=86=E5=85=A5=E6=96=87=E6=A1=A3=E5=B9=B6=E5=BB=BA=E7=AB=8B?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E5=9F=BA=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...56\346\240\207\344\273\273\345\212\241.md" | 444 ++++++++++++++++++ ...06\345\205\245\346\270\205\345\215\225.md" | 140 ++++++ 2 files changed, 584 insertions(+) create mode 100644 "docs/taget/\347\254\254\344\272\224\351\230\266\346\256\265\347\233\256\346\240\207\344\273\273\345\212\241.md" create mode 100644 "docs/taget/\351\230\266\346\256\265\344\272\224\345\207\206\345\205\245\346\270\205\345\215\225.md" diff --git "a/docs/taget/\347\254\254\344\272\224\351\230\266\346\256\265\347\233\256\346\240\207\344\273\273\345\212\241.md" "b/docs/taget/\347\254\254\344\272\224\351\230\266\346\256\265\347\233\256\346\240\207\344\273\273\345\212\241.md" new file mode 100644 index 0000000..3cc4fdd --- /dev/null +++ "b/docs/taget/\347\254\254\344\272\224\351\230\266\346\256\265\347\233\256\346\240\207\344\273\273\345\212\241.md" @@ -0,0 +1,444 @@ +# 第五阶段目标任务:非 AI 体验与本地收口 + +## 0. 阶段状态与适用范围 + +本文件是阶段五的目标任务和实现前契约,不代表本阶段业务已经实现。2026-08-23 的“阶段 5 迭代 0”只完成阶段准入、基线记录和文档落盘;S5-01~S5-09 均待后续迭代实施。 + +阶段五定位为“非 AI 体验与本地收口”:在阶段四已有的公开阅读、评论、工具和搜索基础上,补齐知识星图、终端导航、首页标志性动效、音乐与频谱、404 彩蛋、PWA 离线工具箱,以及重型效果的生命周期和降级边界。 + +本阶段继续遵循“仪器而非装饰、降级是一等路径、可读性永远赢”。首页首幕和文章正文必须不依赖 JavaScript;Three.js、图谱渲染、音频分析和 Service Worker 都不能成为内容可见性的前置条件。 + +## 一、阶段目标与非目标 + +### 1.1 阶段目标 + +- 让文章、标签、分类和工具可以通过受限的知识星图被发现,并在移动端退化为可读的时间线。 +- 提供浏览器内白名单终端,支持导航、搜索和主题切换;任何命令都不连接服务器 Shell。 +- 将首页明确实现为“夜空校准 → 星图接入 → 近期观测日志”三幕,首幕为 SSR 静态内容,第二幕才按需加载 Three.js。 +- 提供默认不自动播放的全局音乐、频谱和波形体验;音频只从服务端配置的受信任 OSS/CDN 清单加载。 +- 提供可跳过、可关闭、移动端可降级的“丢失信号修复”404 小游戏。 +- 让 /tools 的浏览器端工具具备最小范围离线能力,不缓存私有数据、文章正文、评论、Studio 或 API 响应。 +- 在 360/768/1280/1600px、键盘、触摸、prefers-reduced-motion、Save-Data、无 JavaScript和资源加载失败路径下,保持可用和可读。 +- 为阶段六的 2GB 加固保留可测量的资源、缓存、并发和生命周期边界。 + +### 1.2 明确非目标 + +本阶段不实现、不验收以下项目: + +- AI Chat、SSE、RAG、Embedding、选区问答、后台创作、模型额度、费用台账和 AI 评测。 +- 域名、HTTPS、ICP/公安备案、部署、ACR、远端 CI、真实生产环境或云资源变更。 +- 真实 OSS 媒体上传改造、真实 SMTP 投递、备份恢复演练和生产合规材料。 +- 30 分钟压力测试、生产容器内存加固、日志轮转和回滚演练;这些属于阶段六或阶段七的外部/运行验收。 +- Studio 曲目 CRUD、音乐上传、曲目审核或数据库音乐表;音乐只消费服务端配置的受信任 OSS/CDN JSON 清单。 +- 通过终端执行任意 Shell、SQL、文件系统、网络抓取或未列入白名单的命令。 +- 把全文、评论正文、管理数据或任意 HTML/JavaScript放入图谱、PWA 缓存或音乐清单。 +- 全屏粒子、大面积模糊玻璃、传统顶部导航、三列文章卡片、九宫格工具卡片或为动效引入 React Framer Motion。 +- 新建微服务、Redis、消息队列、独立搜索服务、MinIO 或新的数据库表;若实现阶段发现确需改变边界,必须先重新进行阶段准入。 + +## 二、既有基线与架构边界 + +- API 仍是 Java 21 + Spring Boot 模块化单体,业务边界为 identity、content、comment、toolbox、ai、media、site、shared。 +- Web 仍是 Nuxt 4 + Vue 3 + TypeScript;公开站点 SSR,/studio CSR。公共内容契约继续由 OpenAPI 和 packages/api-client 负责。 +- 图谱数据由服务端从已公开的文章、标签、分类和工具读模型生成,不向浏览器发送全文,不由客户端拼接管理数据。 +- 音频二进制不经过 Spring Boot;Nuxt 服务端读取受信任 manifest 的地址,浏览器只接收校验后的清单和允许的 HTTPS 音频地址。 +- 重型客户端模块必须路由或交互懒加载,并在路由离开、组件卸载和 Feature Flag 关闭时释放监听器、计时器、Worker、AudioContext、AnalyserNode、Three.js 场景和纹理。 +- 阶段五不修改现有迁移文件,不创建新迁移;S5-01 的第一版 Feature Flag 采用服务端配置/公开读模型,不做 Studio 配置 CRUD。 + +## 三、任务依赖关系 + +~~~mermaid +flowchart LR + S500["S5-00 阶段准入"] --> S501["S5-01 图谱契约与 Feature Flag"] + S501 --> S502["S5-02 知识星图"] + S501 --> S503["S5-03 安全终端与主题"] + S501 --> S504["S5-04 首页三幕与 Three.js"] + S501 --> S505["S5-05 音乐与频谱"] + S501 --> S506["S5-06 404 信号修复"] + S501 --> S507["S5-07 PWA 离线工具箱"] + S502 --> S508["S5-08 性能、生命周期与降级收口"] + S503 --> S508 + S504 --> S508 + S505 --> S508 + S506 --> S508 + S507 --> S508 + S508 --> S509["S5-09 综合验收与文档"] +~~~ + +依赖原则:S5-01 先冻结公开数据和开关,避免视觉组件各自定义数据;S5-02~S5-07 可以并行开发,但都必须把资源释放和关闭开关交给 S5-08 统一验收;S5-09 只在降级、生命周期和公开契约全部可复现后收口。 + +## 四、公共契约、数据结构与 Feature Flag + +以下是后续实现时必须通过 OpenAPI、Nuxt Server Route 或静态资源契约固化的公开接口。本轮不新增接口代码,也不修改 docs/openapi/public-api.yaml。 + +### 4.1 公开接口 + +| 接口 | 所属 | 目的与硬边界 | +| --- | --- | --- | +| GET /api/v1/public/site | Spring Boot | 在现有站点响应中增加公开的 featureFlags;保留现有 commentsEnabled、ETag 和缓存语义。不返回密钥、内部配置或 Studio 权限。 | +| GET /api/v1/public/knowledge-graph | Spring Boot | 返回受限图谱 JSON;只含公开节点摘要、关系、权重、版本和 ETag,不含 Markdown、评论、未发布内容或管理字段。 | +| GET /music-manifest.json | Nuxt Server Route/静态边界 | 由服务端配置的 HTTPS OSS/CDN manifest 地址提供校验后的清单;不提供 Studio 曲目 CRUD,不代理音频二进制。若源不可用,返回空清单并保留播放器降级文案。 | +| GET /manifest.webmanifest | Web 静态资源 | 只描述公开站点和工具箱的安装元数据,不声明 Studio、评论写入或后台能力。 | +| GET /sw.js | Web 静态资源 | 只负责公开工具箱的最小缓存和更新;不得拦截或持久化 /api/**、/studio/**、评论提交、登录和文章私有预览。 | + +终端、404 游戏、频谱和 Three.js 都是浏览器内功能,不另开 API。终端复用现有公开文章、搜索、工具和站点接口;ask 命令在阶段五只返回“AI 尚未在本阶段开放”的本地提示,不发送 AI 请求。 + +### 4.2 图谱数据结构 + +~~~ts +type KnowledgeGraphNodeKind = 'ARTICLE' | 'TAG' | 'CATEGORY' | 'TOOL' +type KnowledgeGraphRelation = 'TAGGED' | 'CATEGORIZED' | 'RELATED_TOOL' | 'SHARED_TAG' + +interface KnowledgeGraphNode { + id: string + kind: KnowledgeGraphNodeKind + label: string + href: string | null + weight: number + publishedAt?: string +} + +interface KnowledgeGraphEdge { + source: string + target: string + relation: KnowledgeGraphRelation + weight: number +} + +interface KnowledgeGraphResponse { + schemaVersion: 1 + generatedAt: string + nodes: KnowledgeGraphNode[] + edges: KnowledgeGraphEdge[] +} +~~~ + +服务端默认上限为 120 个节点、360 条边;实际值以实现时的资源观测为准,但必须有硬上限。href 只能是站内安全路径,节点标签和类型必须同时表达状态,不能只用颜色区分。移动端无需请求全文,退化视图复用节点的标签、类型和站内链接。 + +### 4.3 音乐清单数据结构 + +~~~ts +interface MusicManifest { + schemaVersion: 1 + defaultTrackId: string | null + tracks: Array<{ + id: string + title: string + artist: string | null + audioUrl: string + coverUrl: string | null + license: 'ORIGINAL' | 'CC_BY' | 'CC_BY_SA' | 'OTHER_AUTHORIZED' + attributionUrl: string | null + }> +} +~~~ + +服务端只信任配置的 HTTPS OSS/CDN 来源和允许的 host;客户端仍需校验 schema、URL 协议、条目数量和必填字段。建议最多 30 首;音频地址只在用户点击播放后才加载,默认不自动播放。每首曲目必须有授权说明或归属链接。 + +### 4.4 Feature Flag + +第一版采用服务端配置并通过 GET /api/v1/public/site 下发;不增加 Studio 开关编辑页面,不把开关写入浏览器可篡改的“真值”。客户端检测到缺失、非法或接口失败时,一律选择关闭重型效果的安全默认值。 + +| Flag | 作用 | 安全默认 | 依赖 | +| --- | --- | --- | --- | +| terminal | 开放 ⌘K/Ctrl+K 白名单终端 | false | 现有公开文章、搜索、工具接口 | +| knowledgeGraph | 图谱 Canvas/Force 视图 | false | S5-01 图谱契约 | +| homeScene | 首页第二幕 Three.js | false | knowledgeGraph 或静态首页数据 | +| music | 全局播放器和清单 | false | 服务端 manifest | +| spectrum | Web Audio 频谱/波形 | false | music、用户播放手势 | +| signalRepair404 | 404 三步修复小游戏 | false | 本地组件 | +| pwa | 工具箱 manifest、Service Worker 和离线缓存 | false | 工具页面 | + +data-theme="night|blueprint" 是用户本地选择,不是远端 Feature Flag;必须使用 html data-theme 和 CSS Token。prefers-reduced-motion、Save-Data、触摸和设备能力属于运行时降级信号,不得被远端开关覆盖。AI 相关开关不在本阶段新增。 + +## 五、详细任务清单 + +### S5-00:阶段准入 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P0,阶段准入 | +| 前置依赖 | 无 | +| 工作量 | 2–4 小时 | +| 公开接口 | 无 | +| 数据结构/Flag | 冻结本文件和准入清单,不创建运行时结构 | + +目标:记录阶段四本地验收基线、当前分支和用户改动,确认阶段五只做非 AI 体验与本地收口。 + +非目标:不恢复被用户删除的阶段四文档,不提交、不推送、不部署,不写业务代码、OpenAPI、迁移或空类。 + +验收标准: + +- 阶段 2/3 历史文档、阶段 4 收口文档的来源和路径差异可追溯。 +- 当前环境命令、API/Web/OpenAPI/Compose 入口和 Git 状态已记录。 +- 阶段五任务、依赖、外部未执行项目和完成定义已落盘。 +- 用户对 AGENTS.md 和完整开发计划的未提交修改保持原样。 + +测试场景:检查 git status --short --untracked-files=all、git diff --check、文档链接和目标路径;不运行会改变业务状态的命令。 + +### S5-01:图谱契约与 Feature Flag + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P0 | +| 前置依赖 | S5-00 | +| 工作量 | 6–10 小时 | +| 公开接口 | GET /api/v1/public/site、GET /api/v1/public/knowledge-graph | +| 数据结构/Flag | KnowledgeGraphResponse、4 类节点、7 个阶段五开关 | + +目标:冻结图谱的最小公开读模型、ETag/缓存、节点上限、站内链接策略和体验开关,让后续组件不自行读取 JPA 实体或管理 API。 + +非目标:不返回全文、不做全文搜索替代、不增加数据库表、不做 Studio 配置 CRUD、不开放 AI 或通用远程配置。 + +验收标准: + +- OpenAPI 中的响应字段与生成客户端一致,DTO 不暴露实体。 +- 只返回已公开文章、已公开工具及其标签/分类关系;草稿、预览、归档和后台字段永不出现。 +- ETag 对图谱版本和影响响应的数据稳定,接口失败时客户端可使用空/静态回退。 +- 开关关闭或响应缺失时,页面仍能显示静态导航和文本内容。 +- 节点和边数量、字符串长度、响应体大小有硬上限。 + +测试场景:空站点、单节点、重复关系、未发布文章、越界节点、ETag/304、未知 flag、损坏 JSON、服务端 5xx 和客户端默认关闭。 + +### S5-02:知识星图 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P1 | +| 前置依赖 | S5-01 | +| 工作量 | 12–18 小时 | +| 公开接口 | GET /api/v1/public/knowledge-graph | +| 数据结构/Flag | 图谱节点/边、knowledgeGraph | + +目标:使用 Canvas + 受限 Force 布局呈现文章、标签、分类和工具的关系;单击显示摘要导航,双击进入安全站内路径。 + +非目标:不在浏览器拉取全文,不引入全量 D3,不做无限缩放、用户编辑关系或实时协作,不依赖 Three.js 才能使用图谱。 + +实现边界:只评估和引入 d3-force/d3-scale 等最小模块,并按路由懒加载;若资源预算不通过,保留同一契约并退回静态 SVG/时间线,不扩大依赖。 + +验收标准: + +- 桌面可键盘聚焦、选择和打开节点;节点类型、标签和关系不只通过颜色表达。 +- 移动端、低性能设备、Save-Data、reduced-motion 或图谱失败时退化为可读时间线。 +- 图谱不进入文章详情初始客户端闭包;离开页面会取消布局、移除监听器并释放 Canvas。 +- 节点数量达到上限时仍可稳定渲染,超限时按公开权重确定性截断。 + +测试场景:空图、最大图、断链、重复节点、键盘导航、触摸点击、双击进入、360px、禁用 JS、Save-Data、reduced-motion、动态块加载失败和路由离开。 + +### S5-03:安全终端与主题 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P1 | +| 前置依赖 | S5-01 | +| 工作量 | 8–12 小时 | +| 公开接口 | 复用文章列表、搜索、工具和站点公开接口;不新增 Shell API | +| 数据结构/Flag | 白名单命令 AST、终端历史上限、terminal、data-theme | + +目标:通过 Dock 或 Ctrl/Cmd+K 打开可访问的命令终端,支持 help、ls posts、ls tools、grep "词"、open /articles/...、theme blueprint 和 theme night。 + +非目标:不执行 Shell/SQL/JS,不读取本地文件,不拼接任意 URL,不实现 AI ask 请求;ask 只能返回阶段未开放提示或转到本地搜索。 + +验收标准: + +- Parser 只接受固定命令和长度上限,未知命令返回文本错误,不抛出页面级异常。 +- 所有路径、搜索词、终端历史和输出均有长度/条数上限;不把用户输入写入 HTML 为可执行内容。 +- Dialog 具备 role="dialog"、aria-modal、焦点陷阱、Esc 关闭和键盘历史;移动端不依赖 hover。 +- theme blueprint 和 Logo 五连击只改变 html data-theme 与 CSS Token;刷新后可恢复,无法写入服务端权限。 +- 不支持 backdrop-filter 时使用不透明背景;reduced-motion 时直接切换状态。 + +测试场景:命令注入字符、超长输入、未授权路径、键盘/触摸、焦点恢复、刷新主题、localStorage 不可用、旧浏览器、ask 降级和公开 API 失败。 + +### S5-04:首页三幕与 Three.js + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P1 | +| 前置依赖 | S5-01;图谱契约可用后接入 S5-02 | +| 工作量 | 12–18 小时 | +| 公开接口 | 复用站点、文章和图谱公开读模型 | +| 数据结构/Flag | 三幕状态、静态 SVG 回退、homeScene | + +目标:实现“夜空校准”SSR 首幕、“星图接入”滚动触发幕、“近期观测日志”SSR 第三幕。Three.js 只在第二幕进入视口后动态导入。 + +非目标:不在首屏加载 Three.js,不让 3D 负责标题/导航/近期文章,不把 3D 放入文章或 Studio 包,不为失败状态显示空白画布。 + +验收标准: + +- 禁用 JavaScript 时首幕标题、说明、导航和近期日志仍在 HTML 中;第三幕仍可阅读。 +- homeScene=false、移动端、Save-Data、reduced-motion、WebGL 不可用或动态块失败时显示静态 SVG/文本关系图。 +- Three.js 与可能的编排模块只进入首页按需 chunk,压缩资源目标小于 500KB;文章初始包不包含它们。 +- 首页离开时销毁 geometry/material/texture/renderer、取消 RAF 和 observers,重复进入不累积资源。 +- 动效只使用 transform/opacity 等合成属性,扫描线和呼吸灯优先 CSS-first。 + +测试场景:SSR/无 JS、首屏不发 3D 请求、滚动触发、快速进出视口、WebGL 失败、动态 import 失败、重复路由进入、360px、Save-Data、reduced-motion、键盘和屏幕阅读器。 + +### S5-05:音乐与频谱 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P1 | +| 前置依赖 | S5-01 | +| 工作量 | 8–12 小时 | +| 公开接口 | Nuxt GET /music-manifest.json;音频由 manifest 指向 OSS/CDN | +| 数据结构/Flag | MusicManifest、播放器状态、music、spectrum | + +目标:提供跨路由持续的轻量播放器和可关闭的 Web Audio 频谱/波形;播放只由用户手势开始,音频不经 Spring Boot。 + +非目标:不自动播放、不做上传和曲目 CRUD、不保存用户音频、不在服务端转码、不把 AudioContext 放进文章首屏,不把外部任意 URL 当作可信音频。 + +验收标准: + +- 服务端只读取配置的 HTTPS manifest 来源,校验 schema、host、协议、授权字段和条目上限;源失败时播放器可隐藏或显示离线提示。 +- 用户未点击播放前不请求音频、不创建持续 AudioContext;浏览器拒绝 autoplay 时页面仍正常。 +- 路由切换不打断播放;离开播放器所有者或关闭频谱时释放 analyser、MediaElementSource、RAF 和事件监听器,不泄漏到 Studio。 +- 频谱失败、Save-Data、reduced-motion、低性能或不支持 Web Audio 时只保留播放控制和静态状态灯。 +- UI 使用 role="region"/适当按钮名称和 aria-live 的低频状态播报;颜色不作为唯一状态。 + +测试场景:合法/损坏/超大/跨域 manifest、非 HTTPS URL、未授权条目、用户手势、暂停/继续、路由切换、音频错误、AudioContext 拒绝、无 Web Audio、Save-Data、reduced-motion 和 Studio 隔离。 + +### S5-06:404 信号修复 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P1 | +| 前置依赖 | S5-01 | +| 工作量 | 4–6 小时 | +| 公开接口 | 复用站内搜索;无专用后端接口 | +| 数据结构/Flag | 本地 RepairState、signalRepair404 | + +目标:在现有 error.vue 中提供轻量三步断点修复游戏,成功后回到首页;失败、关闭或无 JavaScript 时始终保留搜索和文章建议。 + +非目标:不使用 Three.js、Canvas 大场景、网络排行榜、登录、积分、远端存档或阻塞错误页离开。 + +验收标准: + +- 错误页的状态码、标题、原因和可访问的返回路径不依赖游戏脚本。 +- 游戏状态只在内存中保存;移动端、reduced-motion、Save-Data 或 flag 关闭时显示搜索框和建议文章。 +- 任意步骤失败都能重置或跳过;成功后只进行普通站内导航。 +- 控件可键盘操作,断点不只用颜色表达,动效可直接关闭。 + +测试场景:404/500、禁用 JS、flag 关闭、移动端、键盘、重复点击、刷新、游戏失败/成功、搜索接口失败和返回首页。 + +### S5-07:PWA 离线工具箱 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P1 | +| 前置依赖 | S5-01;现有工具箱完成 | +| 工作量 | 8–14 小时 | +| 公开接口 | /manifest.webmanifest、/sw.js;不缓存后台 API | +| 数据结构/Flag | 静态 manifest、缓存版本/白名单、pwa | + +目标:让公开工具箱在已访问并完成安装/缓存后可离线打开,JSON、Base64、URL、时间戳和正则工具仍在浏览器/Worker 内运行。 + +非目标:不离线写入评论或文章,不缓存 API 响应、Cookie、Session、Studio、预览链接、完整文章正文、用户输入或第三方任意脚本,不实现后台同步。 + +验收标准: + +- Service Worker scope 和缓存白名单只覆盖公开工具箱静态资源及明确允许的页面壳。 +- 首次安装、更新失败、缓存损坏、离线未命中和浏览器不支持时都有在线/无 JS 可读回退。 +- 新版本使用可观测的 cache key,旧缓存可控清理;更新期间不删除当前可用版本。 +- 工具输入不写入 Cache Storage、IndexedDB 或日志;Worker 继续遵守既有输入上限和 250ms 正则超时。 +- Lighthouse/Playwright 可验证安装元数据、离线工具路由、缓存边界和在线恢复。 + +测试场景:首次访问、离线打开 /tools、各五个工具、刷新、更新、缓存损坏、网络恢复、API/Studio 不被拦截、无 JavaScript、Save-Data 和浏览器不支持 Service Worker。 + +### S5-08:性能、生命周期与降级收口 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P0 | +| 前置依赖 | S5-02~S5-07 | +| 工作量 | 10–16 小时 | +| 公开接口 | 不新增;验证前述契约的失败和缓存语义 | +| 数据结构/Flag | 降级决策表、资源预算、dispose 清单 | + +目标:把每个重型能力的进入条件、资源预算、关闭路径、异常路径和可观测结果收敛为一套可重复规则。 + +非目标:不做 30 分钟压测、不修改生产容器上限、不引入监控平台、不把“浏览器能运行”当作内存和 CPU 通过。 + +验收标准: + +- 文章初始 JS 继续不超过 180KB gzip;Three.js、图谱、音乐可视化、PWA 安装逻辑不进入文章初始闭包。 +- 360/768/1280/1600px、Chrome Chromium E2E、键盘、触摸、无 JS、Save-Data、reduced-motion 均有自动化或明确手工记录。 +- 每个模块有 onMounted/onBeforeUnmount 或等价清理:AbortController、Observer、RAF、Timer、Worker、AudioContext、Three.js 和缓存更新监听均可重复进入退出。 +- Flag 关闭、运行时能力不足、动态资源失败、接口 5xx 和超时都回到静态可读路径,不出现死按钮、空面板或永久 loading。 +- 页面性能、可访问性和 SEO 不因阶段五效果低于既有阶段四门槛;阶段六再进行 30 分钟资源压测。 + +测试场景:路由快速往返、并发加载图谱/首页/音乐、动态块失败、资源加载超时、低端/移动 viewport、A11y tree、文章 bundle、Lighthouse、控制台未处理异常和缓存清理。 + +### S5-09:综合验收与文档 + +| 属性 | 内容 | +| --- | --- | +| 优先级 | P0,阶段收口 | +| 前置依赖 | S5-08 | +| 工作量 | 8–12 小时 | +| 公开接口 | OpenAPI、Nuxt manifest、Service Worker 与现有公开接口全部复核 | +| 数据结构/Flag | 固定验收数据、Flag 矩阵、降级矩阵、结果记录 | + +目标:将阶段五的公开契约、视觉路径、资源预算、降级和生命周期固化为可重复的本地验收,并同步真实文档命令。 + +非目标:不把本地通过写成远端 CI、真实 OSS/SMTP、备案、部署、生产压测或 AI 通过;不提交、推送或创建 PR。 + +验收标准: + +- 图谱契约与生成客户端无差异;所有新增后端接口均有 Problem Details、ETag/缓存和边界测试。 +- 首页三幕、终端主题、音乐频谱、404、PWA 均有主路径、关闭开关和失败降级路径。 +- 文章 SSR、工具离线、终端安全、音频授权、Service Worker 缓存边界和资源释放均可验证。 +- README、完整开发计划、本地启动指南和阶段五文档只记录真实存在的命令和真实状态;本阶段没有业务实现时不提前勾选完成。 +- git diff --check 通过,未授权的用户改动未被覆盖、恢复、提交或删除。 + +## 六、阶段五测试与验收计划 + +### 6.1 契约与单元测试 + +- API:图谱节点/边截断、公开可见性、稳定 ETag、Feature Flag 默认值、非法 manifest 配置和安全路径校验。 +- Web:终端 parser、主题状态、图谱数据归一化、音乐 manifest 校验、播放器状态机、频谱降级、404 状态机、PWA cache allowlist 和更新策略。 +- OpenAPI:生成 packages/api-client 后执行 check,禁止在 apps/web 手写重复 DTO。 + +### 6.2 浏览器与 SSR 场景 + +- 无 JavaScript打开首页、文章、404 和工具页,标题、正文/工具说明、错误路径和主要导航仍可用。 +- 首次进入首页不请求 Three.js;滚动进入第二幕后才加载,并在离开时释放。 +- 关闭所有阶段五 flags 后页面退回阶段四可用体验,不产生空白区域或报错。 +- 访问 360px、768px、1280px、1600px;键盘完成 Dock、终端、主题、播放器、图谱和 404 操作;触摸不依赖 hover。 +- Save-Data 和 prefers-reduced-motion 下不运行不必要动画;Lighthouse/控制台无回归。 +- 音乐只在用户手势后发起请求;路由切换不泄漏分析器;PWA 离线只支持公开工具箱。 + +### 6.3 安全和资源场景 + +- 终端命令注入、URL 穿越、超长输入、恶意搜索词和 XSS 字符不执行。 +- 图谱节点/链接、manifest 的音频/封面地址和 Service Worker scope 均执行协议、host、长度和数量限制。 +- 文章初始客户端闭包不含 Three.js、图谱重型依赖、编辑器、Worker 或音频分析代码。 +- 动态导入失败、WebGL/Web Audio 不可用、接口 5xx、缓存损坏、第三方资源超时都能回退。 + +## 七、迭代安排与工作量 + +按个人每周 15–20 小时估算,阶段五约 78–122 个理想开发小时,实际取决于图谱可视化和 Three.js 场景的复杂度。建议按以下顺序推进: + +| 迭代 | 任务 | 交付结果 | +| --- | --- | --- | +| 迭代 0 | S5-00 | 阶段准入、基线、任务文档和未执行项目清单 | +| 迭代 1 | S5-01、S5-02 | 图谱契约、开关和静态/桌面图谱闭环 | +| 迭代 2 | S5-03、S5-04 | 终端主题和首页三幕,含 Three.js 关闭回退 | +| 迭代 3 | S5-05、S5-06、S5-07 | 音乐频谱、404 和工具箱最小离线能力 | +| 迭代 4 | S5-08、S5-09 | 生命周期、性能降级、综合验收和文档收口 | + +并行规则:S5-03~S5-07 可以并行,但任何模块进入综合验收前都必须实现对应的关闭开关、无 JS/能力失败回退和卸载清理;没有这些路径,不得以“主路径可用”提前完成。 + +## 八、阶段五最终完成定义 + +阶段五只有同时满足以下条件才算完成: + +- S5-00~S5-09 的任务验收记录完整,且阶段文档、README/启动指南中的命令与真实脚本一致。 +- 知识星图使用受限公开契约,桌面交互可用,移动端和能力不足时退化为时间线;未公开数据和全文不泄露。 +- 终端是浏览器内白名单解析器,主题切换使用 html data-theme;无任何服务器 Shell 或 AI 请求越权。 +- 首页三幕首幕和日志 SSR 可读,Three.js 仅按需加载、文章包外置、离开路由彻底释放,失败时有静态回退。 +- 音乐来自服务端配置的受信任 OSS/CDN JSON 清单,默认不自动播放,音频授权信息可见,频谱可关闭且有 Web Audio 降级。 +- 404 游戏不阻塞错误恢复;PWA 只缓存公开离线工具箱,不缓存私有数据和 API 写入。 +- 360/768/1280/1600px、键盘、触摸、无 JS、Save-Data、reduced-motion、动态资源失败和路由往返通过。 +- 文章初始 JS 不超过 180KB gzip,既有 API/Web/OpenAPI/Compose 基线不回归;阶段六的 30 分钟压力测试和生产资源验收仍单独记录。 +- 本地验收通过不等于真实 SMTP、真实 OSS、域名/备案、部署、远端 CI/生产或 AI/RAG 通过;这些项目在报告中继续明确列为未执行或后续阶段。 + +本迭代完成定义:仅新增本文件和阶段五准入清单;没有业务代码、空类、数据库迁移、OpenAPI 修改、生成客户端改动、提交、推送、PR 或部署。 diff --git "a/docs/taget/\351\230\266\346\256\265\344\272\224\345\207\206\345\205\245\346\270\205\345\215\225.md" "b/docs/taget/\351\230\266\346\256\265\344\272\224\345\207\206\345\205\245\346\270\205\345\215\225.md" new file mode 100644 index 0000000..206e180 --- /dev/null +++ "b/docs/taget/\351\230\266\346\256\265\344\272\224\345\207\206\345\205\245\346\270\205\345\215\225.md" @@ -0,0 +1,140 @@ +# 阶段五准入清单:非 AI 体验与本地收口 + +## 0. 本轮结论 + +本清单对应“阶段 5 迭代 0:阶段准入与规划文档落盘”。本轮只建立可追溯基线和任务文档,不实现阶段五业务功能。 + +- 本轮文档:docs/taget/第五阶段目标任务.md、本文件。 +- 未新增业务代码、空类、数据库迁移、OpenAPI 路径、生成客户端或外部资源。 +- 未提交、推送、创建 PR、部署或修改云资源。 +- 阶段四文档在当前工作树中已经是删除状态;本轮未恢复,阶段四基线从提交 f0bfdac 读取。 + +## 一、Git 基线与用户资产 + +| 项目 | 本轮记录 | +| --- | --- | +| 工作目录 | G:\work\HaoBlog | +| 分支 | codex/s4-01,跟踪 origin/codex/s4-01 | +| HEAD | f0bfdac58e0f9821dd313e879892302eb971bc08(完成阶段四综合验收并收敛项目说明) | +| 最近提交 | f0bfdac、c246517、0b3b5b8、57a03a4、1b066e3、4330ffc、6c24570、a18a7de | +| 阶段五目录 | 本轮前不存在,已创建 docs/taget;该目录名按仓库规则保留为 taget | +| 工作树初始状态 | AGENTS.md 修改;docs/HaoBlog 完整开发计划.md 修改;docs/第四阶段目标任务.md 删除;docs/阶段四准入清单.md 删除;无未跟踪文件 | +| 保留资产 | 上述用户修改全部保留,尤其是完整开发计划中的阶段五边界、PWA/音乐/彩蛋调整;不覆盖、不回退、不恢复删除文档 | + +阶段 2/3 目标文档在当前树不存在:阶段 2 原文从 df6fada68e5fc1ecaabe257115bbfca95d6a20eb:docs/第二阶段目标任务.md 读取,阶段 3 原文从 7a377ab19fec7b829f47308662bb1b981e6fa460:docs/第三阶段目标任务.md 读取。阶段 4 原文从 f0bfdac 的 docs/第四阶段目标任务.md 和 docs/阶段四准入清单.md 读取。阶段 2/3 的历史实际路径在 docs/ 根目录,不在当前工作树的 docs/taget。 + +## 二、阶段四基线 + +阶段四收口文档记录的本地 S4-10 基线如下;这些数字是历史基线,必须以本轮实际命令结果为准,不能替代真实生产或远端 CI 验收: + +- 环境:Windows 11、Java 21.0.11、Node.js 24.14.0、pnpm 11.16.0、Docker Engine 29.7.2、Compose 5.3.1。 +- API:-DskipITs verify Surefire 78/78;PostgreSQL/pgvector Failsafe 53/53。 +- Web:typecheck、Vitest 85/85、Nuxt production build 通过;Chromium Playwright 14/14。 +- OpenAPI:generate、check 和生成文件无差异通过。 +- 文章初始客户端静态闭包 65,244 bytes gzip,小于 180 KiB;Mermaid 位于异步 chunk。 +- Lighthouse:文章页和工具页移动 360×800 的 Performance、Accessibility、SEO 均为 1.00。 +- 生产 Compose 上限:Caddy 64 MiB/0.2 CPU/64 PID,Web 320 MiB/0.6 CPU/128 PID,API 640 MiB/1.25 CPU/256 PID,PostgreSQL 480 MiB/0.8 CPU/128 PID。 +- 未完成的外部项目:真实 SMTP、真实 OSS、域名/HTTPS、备案、ACR/部署、远端 CI/生产、备份恢复和合规材料。 + +阶段五继承的本地硬门槛是:公共 SSR 不回归;文章初始 JS ≤180KB gzip;没有 Three.js 进入文章包;工具、评论、搜索、OpenAPI、Compose 和现有安全边界不回归。30 分钟压测、生产资源运行态和真实外部项目不在本轮通过范围。 + +## 三、本轮实际环境 + +| 命令 | 实际结果 | 状态 | +| --- | --- | --- | +| java -version | OpenJDK 21.0.11 LTS(2026-04-21) | 通过 | +| node --version | v24.14.0 | 通过 | +| corepack pnpm --version | 11.16.0 | 通过 | +| docker version | Client/Server 29.7.2,Docker Desktop 4.86.0 | 通过 | +| docker compose version | v5.3.1 | 通过 | + +以上五条环境命令已实际执行;其余基线命令在文档落盘后按下一节执行并回填结果。pnpm 命令的 Corepack 激活提示不影响最终版本为 11.16.0。 + +## 四、阶段五预定验收命令 + +以下命令是本轮预定执行的本地基线,不表示所有阶段五功能已经存在。命令均从仓库根目录执行;API 命令使用实际存在的 apps/api/mvnw.cmd。 + +### 4.1 工具链与 API/Web/OpenAPI + +~~~powershell +java -version +node --version +corepack pnpm --version +docker version +docker compose version + +Push-Location apps/api +.\mvnw.cmd -DskipITs verify +Pop-Location + +corepack pnpm --dir apps/web typecheck +corepack pnpm --dir apps/web test +corepack pnpm --dir apps/web build +corepack pnpm --filter @haoblog/api-client check +~~~ + +本轮不执行 generate,因为没有 OpenAPI 修改;后续阶段五若实现 S5-01 的 API,必须先执行 corepack pnpm --filter @haoblog/api-client generate,再执行 check 并审阅生成文件 diff。 + +### 4.2 Compose 与工作树 + +~~~powershell +docker compose --env-file .env.example -f infra/compose/compose.dev.yml config +docker compose --env-file infra/compose/.env.ci.example -f infra/compose/compose.prod.yml config +corepack pnpm compose:verify +git diff --check +~~~ + +本轮不启动 Compose、不构建镜像、不创建测试 volume;config 和 compose:verify 只验证解析、资源限制、健康边界和端口约束。 + +## 五、基线实际执行结果 + +本节在命令运行结束后回填。状态只允许使用“通过”“阻塞”“未执行”,不能用历史阶段结果代替本轮结果。 + +| 命令 | 结果 | 状态/阻塞原因 | +| --- | --- | --- | +| java -version | 21.0.11 LTS | 通过 | +| node --version | v24.14.0 | 通过 | +| corepack pnpm --version | 11.16.0 | 通过 | +| docker version | Client/Server 29.7.2 | 通过 | +| docker compose version | v5.3.1 | 通过 | +| apps/api/.\\mvnw.cmd -DskipITs verify | Surefire 78/78,BUILD SUCCESS | 通过 | +| corepack pnpm --dir apps/web typecheck | nuxt prepare、vue-tsc 完成 | 通过 | +| corepack pnpm --dir apps/web test | 19 个测试文件,85/85 | 通过 | +| corepack pnpm --dir apps/web build | Nuxt client/server/Nitro build complete | 通过;有现有依赖 deprecation 和 Vite 大 chunk 警告 | +| corepack pnpm --filter @haoblog/api-client check | openapi-typescript 7.13.0 check 完成 | 通过 | +| dev Compose config | Compose 配置成功解析 | 通过 | +| prod Compose config | Compose 配置成功解析 | 通过 | +| corepack pnpm compose:verify | Compose resource and health boundaries passed | 通过 | +| git diff --check | exit code 0;仅有现有 CRLF 提示 | 通过 | + +## 六、阶段五准入判断 + +开始 S5-01 业务实现前,必须满足: + +- 本文件和 docs/taget/第五阶段目标任务.md 已存在且描述与用户锁定决策一致。 +- API -DskipITs verify、Web typecheck/test/build、OpenAPI check、两套 Compose config、compose:verify 和 git diff --check 均通过;阻塞项必须有环境证据和替代验证,不得口头豁免。 +- 工作树中的 AGENTS.md 和完整开发计划修改仍保持用户原文;阶段四删除文档不因本轮被恢复。 +- 开始业务实现时先从 S5-01 契约和 Feature Flag 入手,再实现图谱与体验组件;不直接创建空类或占位 API。 +- 任何新增依赖先说明当前栈不足、路由懒加载方式和 bundle/runtime 成本;优先 CSS、浏览器原生 API 和现有 Vue 能力。 + +## 七、未执行外部项目与剩余风险 + +以下项目本轮明确未执行,不能在阶段五本地文档通过后宣称完成: + +- 远端 GitHub Actions/CI、镜像推送、ACR、部署和远端生产验收。 +- 真实 OSS/CDN 音乐清单、真实 OSS 媒体上传、真实 SMTP 投递。 +- 真实域名、HTTPS、ICP/公安备案、隐私/评论/AI 合规材料。 +- 数据库备份上传、解密、恢复和 RPO/RTO 演练。 +- 阶段六的 30 分钟 2GB 压测、持续 Swap、OOM、容器资源运行态和回滚演练。 +- AI 基础、SSE、RAG、Embedding、模型供应商、费用和 AI 安全评测。 + +剩余风险:图谱/Three.js/音频分析会增加浏览器内存和首屏后交互成本;低端移动设备和 Safari 的 WebGL/Web Audio 行为需在 S5-08 实机或等价浏览器路径验证;PWA 更新和缓存边界一旦配置错误可能持有旧资源或拦截 API;音乐授权和第三方 CDN 可用性需要真实来源确认;阶段四文档当前不在工作树,后续引用应保持提交来源可追溯。 + +## 八、本轮完成定义 + +- [x] 读取并记录 AGENTS、完整开发计划、阶段 2/3 历史任务、阶段 4 收口文档、设计语言、README 和本地启动指南。 +- [x] 读取并使用 .agents/skills/haoblog-design/SKILL.md 的“仪器而非装饰、降级是一等路径”原则。 +- [x] 记录 Git 分支、HEAD、最近提交、用户未提交修改、阶段四删除状态和未跟踪文件检查。 +- [x] 创建阶段五目标任务和本准入清单。 +- [x] 完成本节“基线实际执行结果”的所有命令并逐项记录。 +- [ ] 阶段五业务功能完成;本轮明确不做。