docs(blog): publish paired English editions and complete indexes - #4701
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审查对象:4701@163cc3cc7d9e06ad2cde7da2a1ee09944a7ebcae(已合并,合并后审计)。merge base 092a28c4e7704828b134e21757edb29924ff9b03,14 个文件 +771/-9。
动机
站点上的 Blog 是双语的:apps/presentation/site/public/blog/ 对应英文,blog/zh/ 对应中文。但在 base 上,英文索引只列了 from-one-shot-agents-to-long-horizon-control 一篇文章,agent-facing-kanban 和 application-scenarios 只有中文版;同时唯一覆盖 Blog 的 examples/frontstage-share-bundle-smoke.mjs 用的是硬编码文章清单,并且对这两篇没有译文的文章直接跳过 hreflang 断言。结果是:缺译文、缺索引项、缺语言互链这三类真实缺陷都不会让任何检查变红——手维护清单本身就是问题来源,每加一篇文章都要重新冒一次风险。这个 PR 把“目录即事实”的规则固化下来,并补上缺失的英文版本与索引项。
改动思路
一条规则、一个所有者:把“双语目录必须成对、每个 locale 索引必须列出全部文章、每篇文章必须带 canonical / 对方语言链接 / en+zh-CN+x-default 互链、成对文章的 section id 必须一致”抽成 validateBilingualBlog(),由新脚本 examples/blog-bilingual-index-smoke.mjs 导出(含 collectArticleSlugs() 从磁盘发现文章集合)。旧的 frontstage-share-bundle-smoke.mjs 不再自带清单,而是直接 import 这个函数拿文章集合,并删掉那处按文章名判断 hreflang 的特例。检查入口接进 .github/workflows/frontstage-pages.yml,同时把新脚本加进 push/PR 两条 path filter,改动内容或改动检查都会触发。
具体改动
- 新增
examples/blog-bilingual-index-smoke.mjs(87 行,无依赖):collectArticleSlugs()用readdir+existsSync(<dir>/index.html)发现文章、排序;validateBilingualBlog()断言两个 locale 的 slug 数组完全相等、两个索引都出现href="<slug>/"、<html lang>、rel="canonical"、对方语言链接、三种 hreflang,并逐篇比较成对文章的<section id>序列。 - 发布内容:新增英文版
blog/agent-facing-kanban/index.html(247 行)、blog/application-scenarios/index.html(201 行)及英文presentation.js、四张英文 SVG 图;英文索引补上这两篇(1→3 条),两篇中文文章补上三种 hreflang 与 EN 语言切换链接。 examples/frontstage-share-bundle-smoke.mjs:改为import { validateBilingualBlog },文章集合由发现结果驱动,删除原有["agent-facing-kanban/","application-scenarios/"]的 hreflang 例外分支。.github/workflows/frontstage-pages.yml:新增 path filter 两项与 “Validate bilingual Blog catalog” 步骤(node examples/blog-bilingual-index-smoke.mjs);apps/presentation/site/README.md记录该不变量与两个 smoke 的职责。
对主干的风险
风险面是公开静态站点与 CI,不涉及运行时代码、LoopX 控制面、CLI/API 或持久化状态,回滚只需还原内容提交或摘掉该步骤。实测:node examples/blog-bilingual-index-smoke.mjs → ok (3 paired articles);两处变异都按预期失败——(1) 从英文索引删掉 href="application-scenarios/" 报 Blog index must link every en article: application-scenarios;(2) 只给英文 agent-facing-kanban 插入 <section id="mutation-probe"> 报 Paired Blog article sections must match: agent-facing-kanban。两点保留意见(均非阻塞,P3):断言基于渲染后 HTML 的子串匹配,理论上可被无关出现满足,结构性更强的部分是与成对 section id 的比较;本地跑完整 frontstage 链时卡在 examples/goal-channel-frontstage-fixture.py(PATH 上 python3 为 3.9.6,不支持 dataclass(slots=True)),该失败在 merge base 上同样复现,属既有机器环境限制,非本 PR 引入,因此这一步以合并后的 CI 结论为准。新英文页面的浏览器渲染未在本地验证,仅由静态 HTML 断言与 CI 覆盖。
我的整体评价
这是一个小而完整的收口:既补上了用户可见的缺失内容(两篇英文文章 + 两个索引项),又把导致缺陷长期潜伏的手维护清单换成了目录驱动的机器校验,并且让旧 smoke 复用同一规则而不是再存一份。迁移成本为负——删掉的清单比新增的检查更多;两处变异证明该检查确实会失败而不是空转。作为已合并精确 head 的合并后审计,证据支持通过。
English verdict: APPROVE (exact head 163cc3c)
Goal And Delivered Outcome
/blog/listed one post and the two corresponding English routes did not exist; it now lists all three posts, both newer articles have complete English pages, English diagrams or interaction copy, reciprocal language navigation, and canonical alternates. The focused source test and share-bundle integration row below dynamically discover and verify the bilingual catalog.mainat092a28c4e7704828b134e21757edb29924ff9b03.Scope And Continuation
Validation
163cc3cc7d9e06ad2cde7da2a1ee09944a7ebcaeunitpassednode examples/blog-bilingual-index-smoke.mjs; fast source-level discovery verifies three paired articles, both locale indexes,lang, canonical URLs,hreflang, counterpart links, visible titles, and paired section identities. Wired into Frontstage Pages CI.integrationpasseduv run --extra test node examples/frontstage-share-bundle-smoke.mjs; built the public site, reused the bilingual validator against packaged output, and verified static fallback, scripts, diagrams, and repository-base links.staticpassednode --checkfor the English interaction and bilingual-check scripts,xmllint --nooutfor all four English SVGs,examples/frontstage-pages-workflow-smoke.py, andgit diff --check origin/main...HEAD.manualpassedregression_paritypassedstaticpassedloopx canary premerge --from-git-diff --git-diff-base origin/main --tier standard: 10 catalog canaries, 8 content-ops risk checks, diff hygiene, and the public-boundary scan passed with no manual holds. The initial earlier run exposed only a missing declared TypeScript parser dependency in the clean worktree; afternpm ci --ignore-scripts, the failed semantic-vocabulary check and both subsequent full gates passed without lowering coverage.Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
N/A. This PR does not claim shared Goal Authority or control-plane migration progress.
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).