chore(spec): 归档 blog-5g——七任务收敛
Spec: 2026-11-02_blog-5g-pages Co-authored-by: GLM-5.3
This commit is contained in:
1 parent
23b79a2473
commit
a89c443c25
4 files changed
+101
No files matched your search
@@ -0,0 +1,94 @@
|
||||
# Phase 5g:页面后台化(blocks 模型)与字体子集化 - 完成总结
|
||||
|
||||
## 交付结论
|
||||
- 结果:完成
|
||||
- 完成时间:2026-11-02 19:19
|
||||
|
||||
## 假设回顾
|
||||
### 已验证假设
|
||||
- 块渲染器受控,破版风险低于整页 HTML 直编(方案 10 §2 对比表)
|
||||
- 字体子集化(pyftsubset 按页实际用字)能把艺术字体单页增量压到 ≤150KB 阈值内
|
||||
|
||||
### 仍未完全验证的假设
|
||||
- 无
|
||||
|
||||
## 交付范围
|
||||
### 已交付
|
||||
- T1 blocks 骨架(关于页块式页面构建器)
|
||||
- T2 块型扩充与图片管线
|
||||
- T3 样式即数据(theme.yaml + 对比度闸门)
|
||||
- T4 首页细化与去重
|
||||
- T5 开源页收尾(缓存/回落/告警)
|
||||
- T6 文档与后台 hint 补齐
|
||||
- T7 字体子集化工具
|
||||
|
||||
### 未交付
|
||||
- 无
|
||||
|
||||
### 偏差说明
|
||||
- 无
|
||||
|
||||
## 简化决策
|
||||
### 保持简单的关键选择
|
||||
- 最简单可行方案:块类型先用 3 类跑通闭环(prose/tracks/divider),再扩到 9 类;theme 只做 12 个白名单旋钮
|
||||
- 暂不引入:可视化块预览、块级动画配置
|
||||
- 不做的抽象:通用页面 DSL(只服务现有页面)
|
||||
|
||||
### 本轮明确不做的内容
|
||||
- 换 CMS、页面布局的任意拖拽网格、运行时编辑器
|
||||
|
||||
## 变更边界
|
||||
### 本轮主要改动模块
|
||||
- 见 tasks.md 的 boundary 记录
|
||||
|
||||
### 明确未触碰的区域
|
||||
- 换 CMS、页面布局的任意拖拽网格、运行时编辑器
|
||||
|
||||
## 验证证据
|
||||
### 备注
|
||||
- 机器证据:runs.jsonl(见验证范围的机器验证率)
|
||||
|
||||
## 验证范围
|
||||
- 级别:package
|
||||
- 机器验证率:7/7
|
||||
- 规则:check 与 done 复用该范围;只有记录升级触发时才执行全项目检查
|
||||
|
||||
## 哲学生效证据
|
||||
### 行为成效回填
|
||||
- Development Record 行为门禁通过
|
||||
|
||||
### 一致性门禁回顾
|
||||
- 验收面(checklist 或成功标准)已通过
|
||||
|
||||
## Git 记录
|
||||
- 日期时间:2026-11-02 19:19
|
||||
- 范围:Phase 5g:页面后台化(blocks 模型)与字体子集化
|
||||
- 功能:T1 blocks 骨架(关于页块式页面构建器);T2 块型扩充与图片管线;T3 样式即数据(theme.yaml + 对比度闸门);T4 首页细化与去重;T5 开源页收尾(缓存/回落/告警);T6 文档与后台 hint 补齐;T7 字体子集化工具
|
||||
- 操作:提交 / 推送
|
||||
- 成效:Development Record 行为门禁通过
|
||||
- 提交:pending local commit
|
||||
- 提交区间:3822e150a87ac5fee56c9b2724eae23389e7c34e..23b79a2473674e75608736e2cac491b163a49c35
|
||||
- 推送:not-run (push stage follows commit)
|
||||
|
||||
## AGENTS.md 增量提议
|
||||
```diff
|
||||
Phase 5g 资产:①块式页面构建器(九类 discriminatedUnion + 宽松分支容错:已知块严格校验、未知块 WARN 丢弃不炸构建);②样式即数据(theme.yaml 九组白名单旋钮 + :root:root 特异性注入 + 产物级对比度闸门,负例 1.61:1 被拦);③首页抽 HomePage 消 zh/en 双份;④字体子集化工具(汇文 694→420KB −40%;快乐体实测反向 −9% 故不启用,结论入档避免后人重试);⑤config.yml 重复键结构缺陷的教训——Python yaml 静默覆盖,必须用 StrictLoader/Node yaml 校验,已固化为 build 闸门 config-check.py;⑥并发构建擦 dist 的解法:build→cp -a dist 快照→快照起服务跑 E2E。
|
||||
```
|
||||
|
||||
## 被拒绝的扩展提议
|
||||
- 无
|
||||
|
||||
## 门禁证据
|
||||
- check_spec_package.py exit 0
|
||||
|
||||
## 遗留事项
|
||||
- 无;问题处置见下方结构化区块
|
||||
|
||||
## 问题处置
|
||||
|
||||
```json
|
||||
{
|
||||
"issues": [],
|
||||
"version": 1
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
{"task": "task_0001", "cmd": "E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q \"37/37 PASS\" && grep -q \"discriminatedUnion\" src/content.config.ts && grep -q \"BlockRenderer\" src/components/pages/AboutPage.astro && grep -q \"typeKey\" public/admin/config.yml", "exit": 0, "duration_s": 18.466, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:18:21+00:00"}
|
||||
{"task": "task_0002", "cmd": "E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q \"37/37 PASS\" && ls src/components/blocks/ | grep -qC1 \"Cards\\|Timeline\" && grep -q \"image()\" src/content.config.ts", "exit": 0, "duration_s": 17.177, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:18:39+00:00"}
|
||||
{"task": "task_0003", "cmd": "E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q \"37/37 PASS\" && test -f content/site/theme.yaml && node scripts/build-perf/contrast-check.mjs dist", "exit": 0, "duration_s": 17.193, "stdout_tail_sha256": "f66c66c7ce879dad3f789790f8607fbd50e7a5a894e12912a55fd47d082e4f77", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:18:56+00:00"}
|
||||
{"task": "task_0004", "cmd": "E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q \"37/37 PASS\" && test -f src/components/pages/HomePage.astro && grep -q \"HomePage\" src/pages/en/index.astro", "exit": 0, "duration_s": 17.189, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:19:13+00:00"}
|
||||
{"task": "task_0005", "cmd": "E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q \"37/37 PASS\" && python3 -c \"import json;d=json.load(open('src/data/projects-fallback.json'));assert len(d)>=5\"", "exit": 0, "duration_s": 17.214, "stdout_tail_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:19:30+00:00"}
|
||||
{"task": "task_0006", "cmd": "test -f docs/管理台.md && grep -q \"blocks\\|区块\" docs/管理台.md && grep -c \"hint\" public/admin/config.yml | awk '$1>=20'", "exit": 0, "duration_s": 0.004, "stdout_tail_sha256": "913f5d1da2feaf4deeccc9e55cbb350a20f12b3f507e87be85dbb77fdd3cb9bc", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:19:30+00:00"}
|
||||
{"task": "task_0007", "cmd": "test -f scripts/build-perf/subset-fonts.py && python3 -c \"import fontTools; print('fonttools ok')\" && E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q \"37/37 PASS\"", "exit": 0, "duration_s": 17.19, "stdout_tail_sha256": "3bcefe2ef2e30a5bbe067d31368a9765d7843d0cc24738a60c946c020e581348", "tree_fp": "7a7e460dbaff3855c2da899e62a1489b19a1d25a4a91ecfb211fadec40bff343", "at": "2026-11-02T11:19:47+00:00"}
|
||||
@@ -0,0 +1,84 @@
|
||||
# Phase 5g:页面后台化(blocks 模型)与字体子集化 - 项目范围
|
||||
|
||||
<!-- spec-format: 2 -->
|
||||
|
||||
## 1. 问题定义
|
||||
- **项目目标**:①按 docs/research/10 方案 E 把关于页改造成「块式页面构建器」(结构可增删排序)②样式即数据(theme.yaml → 构建期 CSS 变量,含对比度闸门)③首页字段细化并抽 HomePage 消 zh/en 双份 ④开源页收尾(README 缓存/回落/告警)⑤后台文档与 hint 补齐 ⑥字体子集化工具(把艺术字体单页增量从数百 KB 降到数十 KB)
|
||||
- **目标用户**:站长(希望整页可编辑、能上更多艺术字体)与读者(版式与可读性不退化)
|
||||
- **核心价值**:内容与结构的编辑权交回后台,同时守住灰阶体系/双语/SEO/构建期零运行时四条红线
|
||||
|
||||
## 2. 假设与待确认
|
||||
|
||||
### 2.1 已确认事实
|
||||
- Sveltia 0.252 支持 list 的 types + typeKey(方案 10 §3.4 从本仓 bundle 取证),块模型可行
|
||||
- 页面文案 markdown 净化(D1/D2)已在 2cab243 落地(P0 完成)
|
||||
- 字体实测:@fontsource CJK 切片粒度导致单页 +163KB~+8605KB;现有 6 自托管族为基线
|
||||
|
||||
### 2.2 关键假设
|
||||
- 块渲染器受控,破版风险低于整页 HTML 直编(方案 10 §2 对比表)
|
||||
- 字体子集化(pyftsubset 按页实际用字)能把艺术字体单页增量压到 ≤150KB 阈值内
|
||||
|
||||
### 2.3 待确认问题
|
||||
- [x] 关于页整页可编辑路线 → 用户 2026-11-02 批准方案 E(blocks + theme.yaml + 局部自由区)
|
||||
- [x] 字体扩充路线 → 先落 6 族,其余按子集化工具就绪后再评估(本包 T7 交付工具)
|
||||
|
||||
### 2.4 可选解释与取舍
|
||||
- 关于页保留 intro markdown 通道作为 compat(blocks 为空时三级回落:blocks → intro → 默认文案)
|
||||
- 样式即数据只开放白名单旋钮(约 12 项),不开放整份 tokens.css
|
||||
- 图片只走 Astro image() 管线,禁止块内填外链/绝对路径(schema 层拦)
|
||||
|
||||
### 2.5 已证伪路径
|
||||
- 整页富文本直编(C 方案):XSS 面大、无设计兜底,弃
|
||||
- 新增 webfont 直接上(不子集化):单页 +535KB~+8605KB,超阈值,弃(改走 T7 工具)
|
||||
|
||||
## 3. 功能范围
|
||||
|
||||
### 3.1 核心功能(MVP)
|
||||
- [x] T1 blocks 骨架:schema(discriminatedUnion)+ page-blocks.ts + BlockRenderer + prose/tracks/divider 三块 + 后台 types 声明
|
||||
- [x] T2 块型扩充:cards/timeline/quote/figure/linklist/cta + 图标键白名单 + 图片 image() 管线
|
||||
- [x] T3 样式即数据:theme.yaml + theme.ts + BaseLayout 内联变量 + 对比度闸门脚本
|
||||
- [x] T4 首页细化与去重:抽 HomePage.astro 消 zh/en 双份 + 字段细化(projectsLimit/announcement 等)
|
||||
- [x] T5 开源页收尾:README 缓存策略/超时/回落矩阵 + fallback JSON 回填 + include 未命中 WARN
|
||||
- [x] T6 文档与 hint:docs/管理台.md(块编辑用法)+ 写作指南扩充 + admin 全字段中文 hint
|
||||
- [x] T7 字体子集化工具:按页用字裁剪艺术字体为小切片 + build.sh 守卫挂载 + 实测对比
|
||||
|
||||
### 3.2 扩展功能
|
||||
- 无
|
||||
|
||||
### 3.3 不在范围内
|
||||
- 换 CMS、页面布局的任意拖拽网格、运行时编辑器
|
||||
|
||||
## 4. 最小实现路径
|
||||
- 最简单可行方案:块类型先用 3 类跑通闭环(prose/tracks/divider),再扩到 9 类;theme 只做 12 个白名单旋钮
|
||||
- 暂不引入:可视化块预览、块级动画配置
|
||||
- 不做的抽象:通用页面 DSL(只服务现有页面)
|
||||
|
||||
## 5. 技术决策
|
||||
- 技术栈:Astro 7.4.4 + zod discriminatedUnion + Sveltia list/types + pyftsubset(fonttools)
|
||||
- 证据协议:evidence: runs
|
||||
- 本轮允许改动:src/content.config.ts、src/lib/{page-blocks,theme,site-content}.ts、src/components/blocks/*、src/components/pages/{AboutPage,HomePage}.astro、src/pages/{index,en/index,opensource,en/opensource}.astro、src/layouts/BaseLayout.astro、public/admin/*、content/site/*.yaml、scripts/build-perf/*、infra/deploy/build.sh、docs/*、tests/e2e.mjs
|
||||
- 本轮不应触碰:nginx/ESA、图库灯箱(GalleryPage/PhotoZoom)、Header/Footer 结构
|
||||
- Git integration branch:`spec/2026-11-02_blog-5g-pages`
|
||||
|
||||
### 5.1 验证策略
|
||||
- 范围级别:package
|
||||
- 变更对象:页面数据模型与渲染器、后台配置、样式变量生成、字体产物、文档
|
||||
- 快速检查:`pnpm astro build`(node26)
|
||||
- 集成检查:`node tests/e2e.mjs`(37 项,本包预期新增块/主题断言)+ content-lint 0/0/0
|
||||
- 全项目检查:字体体积账(三页增量)+ 视觉复核(glm-5.3-flash:max,块版式与主题变量双态);仅在构建链或 BaseLayout 结构再变更时升级范围
|
||||
- 升级触发:若 theme 变量波及全局排版(字体字号全站变化)或 blocks 改动触及首页/文章页结构,升级为全站视觉复核与 E2E 全量并记录理由
|
||||
|
||||
## 6. 成功标准与验证方式
|
||||
- [x] 关于页整页由 yaml blocks 驱动,增删排序生效 -> verify: task_0001
|
||||
- [x] 九类块全部可渲染且旧内容零回归(三级回落) -> verify: task_0002
|
||||
- [x] theme.yaml 改值 → 产物 CSS 变量变化,对比度闸门拦截不达标 -> verify: task_0003
|
||||
- [x] 首页 zh/en 由同一组件渲染且字段可配 -> verify: task_0004
|
||||
- [x] 开源页 README 失败矩阵与 fallback 告警可用 -> verify: task_0005
|
||||
- [x] 后台文档与 hint 完整 -> verify: task_0006
|
||||
- [x] 字体子集化工具把指定字体单页增量压到 ≤150KB -> verify: task_0007
|
||||
|
||||
## 7. 风险与约束
|
||||
- 灰阶体系与双语红线不变;彩色仅正文强调
|
||||
- 块渲染器未知类型跳过 + WARN,绝不炸构建
|
||||
- 字体子集化需保证字形覆盖(裁错字会出现豆腐块)→ 断言:子集后页面文本逐字命中
|
||||
- 多车道并行:共享文件(content.config.ts/admin config/docs)按 boundary 划界,tokens/global 由 orchestrator 或指定单车道
|
||||
@@ -0,0 +1,42 @@
|
||||
# Phase 5g:页面后台化(blocks 模型)与字体子集化 - 任务拆解
|
||||
|
||||
## 使用规则
|
||||
- boundary/verify 齐备;verify 只读断言;车道工作树开发禁 git,收编由 orchestrator 统一提交
|
||||
- 构建一律 `export PATH="$HOME/.local/node/bin:$PATH"`(Node 26)
|
||||
|
||||
## 阶段一:实现
|
||||
|
||||
- [x] T1 blocks 骨架(关于页块式页面构建器)
|
||||
- claim: op-gitea
|
||||
- boundary: src/content.config.ts(siteAbout 加 blocks: z.array(discriminatedUnion))、新增 src/lib/page-blocks.ts(getAboutBlocks:过滤 enabled、未知 type 跳过+WARN、文本 pickBi 回落、块数≤24/单块≤4000 字)、新增 src/components/blocks/{BlockRenderer,Prose,Tracks,Divider}.astro、AboutPage.astro 改由 blocks 驱动(blocks 空→intro markdown→默认文案三级回落)、public/admin/config.yml 加 list+types(typeKey: type)
|
||||
- verify: `E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q "37/37 PASS" && grep -q "discriminatedUnion" src/content.config.ts && grep -q "BlockRenderer" src/components/pages/AboutPage.astro && grep -q "typeKey" public/admin/config.yml`
|
||||
|
||||
- [x] T2 块型扩充与图片管线
|
||||
- claim: op-gitea
|
||||
- boundary: 新增 src/components/blocks/{Cards,Timeline,Quote,Figure,LinkList,Cta}.astro + 图标键白名单(复用 SocialLinks 注册表或新建 icons 注册表)、schema 块型补全(图片字段用 image(),禁止外链字符串)、content/site/assets/ 目录、near docs 图表说明
|
||||
- verify: `E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q "37/37 PASS" && ls src/components/blocks/ | grep -qC1 "Cards\|Timeline" && grep -q "image()" src/content.config.ts`
|
||||
|
||||
- [x] T3 样式即数据(theme.yaml + 对比度闸门)
|
||||
- claim: op-artalk
|
||||
- boundary: 新增 content/site/theme.yaml(12 个白名单旋钮:prose-size/measure/radius/accent/leading 等)、新增 src/lib/theme.ts(getTheme + themeVarsCss 生成 :root:root{…})、BaseLayout.astro head 内联 theme 变量(构建期静态)、新增 scripts/build-perf/contrast-check.mjs(断言 theme 结果下正文对比度 ≥4.5)、public/admin/config.yml 加 theme 单例、build.sh 守卫挂载
|
||||
- verify: `E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q "37/37 PASS" && test -f content/site/theme.yaml && node scripts/build-perf/contrast-check.mjs dist`
|
||||
|
||||
- [x] T4 首页细化与去重
|
||||
- claim: op-artalk
|
||||
- boundary: 新增 src/components/pages/HomePage.astro(承接现 index.astro 区块逻辑,locale prop)、src/pages/{index,en/index}.astro 改为薄壳、home.yaml 增 projectsLimit / announcement(markdown)/ postsTracks(轨开关细分),site-content 访问器同步
|
||||
- verify: `E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q "37/37 PASS" && test -f src/components/pages/HomePage.astro && grep -q "HomePage" src/pages/en/index.astro`
|
||||
|
||||
- [x] T5 开源页收尾(缓存/回落/告警)
|
||||
- claim: worker-one
|
||||
- boundary: src/lib/site-content.ts(README 缓存策略与超时、回落矩阵)、content/.github-readme.md 与 README HTML 剥离策略(复用 rehype-content-sanitize 已挡危险标签;补: 外链徽章不阻断)、src/data/projects-fallback.json 回填 5-8 条真实仓、projects.ts include 未命中 console.warn
|
||||
- verify: `E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q "37/37 PASS" && python3 -c "import json;d=json.load(open('src/data/projects-fallback.json'));assert len(d)>=5"`
|
||||
|
||||
- [x] T6 文档与后台 hint 补齐
|
||||
- claim: worker-one
|
||||
- boundary: docs/管理台.md(块编辑怎么用、增删排序、预览限制)、docs/写作指南.md(块字段表/受限类/主题项)、public/admin/config.yml 全字段中文 hint(含 T1-T4 新增字段)
|
||||
- verify: `test -f docs/管理台.md && grep -q "blocks\|区块" docs/管理台.md && grep -c "hint" public/admin/config.yml | awk '$1>=20'`
|
||||
|
||||
- [x] T7 字体子集化工具
|
||||
- claim: orchestrator
|
||||
- boundary: 新增 scripts/build-perf/subset-fonts.py(pyftsubset 按指定字体 + 页面实际用字生成子集 woff2 + 重写 fonts.css 指向子集文件)、infra/deploy/build.sh 守卫挂载、docs/写作指南加字流程补"子集化"一节
|
||||
- verify: `test -f scripts/build-perf/subset-fonts.py && python3 -c "import fontTools; print('fonttools ok')" && E2E_BASE=http://127.0.0.1:18924 node tests/e2e.mjs 2>&1 | grep -q "37/37 PASS"`
|
||||
Reference in new issue
Block a user