Skip to content

fix(spec): 参考文档模块标题改为声明式,qa 不再渲染成 "Qa Protocol" (#5853) - #6308

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-5853-category-title-abbreviations
Aug 7, 2026
Merged

fix(spec): 参考文档模块标题改为声明式,qa 不再渲染成 "Qa Protocol" (#5853)#6308
os-zhuang merged 2 commits into
mainfrom
claude/issue-5853-category-title-abbreviations

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#5853

现象

build-docs.ts 过去按目录名模块标题:默认首字母大写,再对 ['UI', 'AI', 'API'] 这三个当初有人想到的缩写做全大写例外。qa 同样是缩写 —— src/qa/index.ts 自己的文件头写的就是 "Quality Assurance (QA) Protocol" —— 但不在名单里,于是生成器单方面把它降级成 "Qa Protocol",一次发布到三处。

判断:为什么不是「把 QA 加进名单」就完事

立单方把这个形状问题明确留给接手方判断。按测量而不是口味决定:

测量项数值
packages/spec/src/ 下模块目录17(readdirSync 运行时发现,无任何机制提醒补名单)
其中是缩写的4(aiapiuiqa)
旧名单覆盖3 —— 在它唯一服务的那一类上漏报 25%
能发现它的门禁0

最后一行是决定性的。check:docs 比对的是「生成结果 vs 已提交结果」,而一个错误的标题是稳定的,所以它永远是绿的。Qa Protocolsrc/qa/ 建立那天起熬过了每一次重生成,直到 #4759 把 14 个标题并排印出来,Qa Protocol 夹在 AI / API / UI 中间才被人眼看见。

所以真正的缺陷不是「漏了一个缩写」,而是猜出来的标题错得无法被发现。只加 QA 会修好这一个实例,把下一个 iam / rbac / sso 目录留给同样的沉默。

也评估了、但被证据否掉的选项

  • 「查表 + 兜底」:把名单换成 CATEGORY_TITLE_OVERRIDES 但保留推导兜底 —— 一无所获。缺条目仍然落回首字母大写,仍然沉默。数据搬了家而已,不满足「缺条目必须可见」。
  • src/*/index.ts 文件头推导标题:看着很吸引人(源侧已经知道正确写法),但实测不可行。逐个读了 17 个文件头:automation / data / identity / kernel 根本没有模块 doc block;security 的头写的是 "Permission Protocol Exports"(会把 security 悄悄改名成 Permission);contracts 写的是 "ObjectStack Contracts"。换成推导会同时制造改名和空标题两类新缺陷。

现在的形状

标题在 scripts/lib/category-title.ts 里逐个声明(CATEGORY_TITLES),该表对磁盘上的目录全覆盖:

  • 没有兜底,也没有推导 —— 已经没有东西可以悄悄出错了;
  • resolveCategoryTitles() 是构造这张映射的唯一入口,双向缺口一律抛错。检查放在构造函数内部而不是旁边,所以后来的调用方拿不到一张没被检查过的 CATEGORIES;
  • 新增模块目录会让 gen:docs直接失败并指名道姓地告诉你补哪一行。

这是刻意沿用旁边 CATEGORY_BLURBS 在一个数据项上已经用了的惯例(blurbCoverage / formatBlurbCoverage,#4759)—— 标题只是最后一个还在靠猜的按模块数据项。新增目录的成本是一行,而且落在同一个 PR 里本来就必须补 blurb 那一行的位置旁边,错误信息会告诉你写什么。⛔ 没有做成通用标题配置系统。

重生成范围

content/docs/references/** 全部由 pnpm --filter @objectstack/spec gen:docs 重生成,⛔ 无任何手改。分支基于#6211(#5340)与 #6224(#5553 + #6136)之后的 main,合并 origin/main 后再次整体重生成 —— 零漂移,证明确实是当前的。

diff 恰为 4 行:

落点变化
content/docs/references/qa/index.mdxtitle: Qa Protocoltitle: QA Protocol
content/docs/references/qa/meta.json侧边栏标签同上
content/docs/references/index.mdx导航行 + 章节标题

description: 那行没有变,因为两种拼写 .toLowerCase() 后都是 qa protocol —— 这是事先预测、事后核对的。

Pin

packages/spec/scripts/category-title.test.ts,12 个用例,按 root-index.test.ts 的两段式惯例(渲染器 + 已提交产物):

  1. :qa 解析为 QA Protocol;四个缩写模块全部保持大写;声明的 key 与磁盘上的目录双向相等。
  2. 可见性属性(即这个形状唯一要买到的东西):一个没有条目的新目录被指名报告,resolveCategoryTitles 抛错且错误信息里带目录名、要改的文件、要补的那一行。这条断言必须被删掉、而不是改一改,才能让沉默回来。
  3. 产物:三处已提交落点各自读作 "QA Protocol",外加全树扫描 content/docs/references/**Qa Protocol 出现 0 次。

反向验证 —— 方向比预测的更强,如实记录

预测的方向是「把推导改回去 → 产物退回 Qa Protocol → pin 变红」。实测拿到了两个方向,第二个比预测的强:

(a) 删掉 qa 声明:生成器根本不生成,而不是生成一个错标题 —— 退出码 1,一个字节都没写:

+ qa (directory exists, no title — add one line: qa: '...')

这正是选这个形状要买的可见性属性,活的证据。只有在「映射全覆盖、无兜底」时才可能出现;若做成「查表 + 兜底」,这一步会安静地产出 Qa Protocol

(b) 把 #5853 之前的推导形状整个还原:gen:docs绿色退出,并把 Qa Protocol 重新发布回全部四处;此时 pin 4 红 8 绿 —— 红的恰是三处产物断言 + 全树扫描,绿的是表/覆盖率单测(因为我只还原了 build-docs.ts,lib 未动)。这个红绿切分本身就是「产物断言确实吃到生成器」的证据。

验证

  • pnpm --filter @objectstack/spec check:docs✅ 232 generated files in sync with packages/spec
  • pnpm --filter @objectstack/spec test333 files / 8504 tests passed
  • pnpm --filter @objectstack/spec typechecktsc --noEmit 通过 + check:test-typecheck: OK
  • eslint 三个改动文件 → 0 问题;check-nul-bytes OK;check:empty-changeset1 declaring changeset(s) added

Changeset

@objectstack/specpatch(具名)。content/docs/references/** 是已发布面,读者看到的标题变了 —— 与今天同类 PR(#6224 / #6134 / #5550)一致。⛔ 非空 frontmatter。

范围

⛔ 未碰 packages/spec/src/**/*.zod.ts、strictness ledger、content/docs/releases/。⛔ 未碰 lib/format-type.ts —— #6225(顶层长枚举仍渲染成单个 6092 字符单元格)排在本单之后,是独立的一单。


Generated by Claude Code

build-docs.ts 过去按目录名猜标题:默认首字母大写,只对 ['UI','AI','API']
这三个当初有人想到的缩写做全大写例外。qa 同样是缩写(src/qa/index.ts 的
文件头就写着 "Quality Assurance (QA) Protocol"),但不在名单里,于是被
单方面降级成 "Qa Protocol",一次发布到三处:分类页标题、qa/meta.json 的
侧边栏标签,以及 references/index.mdx 的导航行与章节标题。
测量到的形状问题(而不是「漏了一个缩写」):
- src/ 下 17 个模块目录由 readdirSync 运行时发现,没有任何东西提醒补名单;
- 其中 4 个是缩写(ai/api/ui/qa),名单覆盖 3 个 —— 25% 漏报;
- check:docs 比对「生成 vs 已提交」,而错误的标题是稳定的,所以永远绿。
这就是 Qa Protocol 熬过每一次重生成、直到 #4759 并排印出 14 个标题才被
人眼发现的原因。猜出来的标题错得无法被发现。
改法:标题在 scripts/lib/category-title.ts 里逐个声明,对磁盘目录全覆盖,
无兜底无推导;resolveCategoryTitles() 是构造该映射的唯一入口,双向缺口
抛错。新增模块目录会让 gen:docs 指名失败并给出要补的那一行,而不是默默
发布 "Iam Protocol"。沿用旁边 CATEGORY_BLURBS 的既有惯例(blurbCoverage /
formatBlurbCoverage,#4759)。
content/docs/references 由 pnpm --filter @objectstack/spec gen:docs 重生成,
diff 恰为 4 行。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
@vercel

vercelBot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 7, 2026 1:32pm

Request Review

@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation tests tooling labels Aug 7, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 0 changed package(s). ✅

@os-zhuangClaude

Copy link
Copy Markdown
ContributorAuthor

PM 验收:ACCEPT — 已 ready + auto-merge。

CI 复核:24 个 check,23 success + 1 按设计 skipped(Console Pin Gate),零 failure。ESLint success、TypeScript Type Check success(13:48:06)、Build Docs success、Test Core 1..3/3 + 聚合 success、Check Changeset 首跑即 success(本单带真 changeset,不适用今日那条标签竞态)。判定前确认 Test Core 在名单中。

文件面 7 个,逐一核过:.changeset/、三处生成物、build-docs.ts、新 pin、新 lib/category-title.ts生成部分恰好 4 行,与你声称的一致;description: 行确未移动(两种拼写 .toLowerCase() 后同为 qa protocol)—— 事先预测、事后核对,这一步做得对。未碰 lib/format-type.ts(#6225/#6226 排在后面)、*.zod.ts、严格度台账、content/docs/releases/

我把这个形状判断记为本轮最好的一次

派发令要求「按测量而非口味决定」,并警告不要把它做成通用标题配置系统。你两条都做到了,而且把缺陷重新定义对了:

真正的缺陷不是「漏了一个缩写」,而是猜出来的标题错得无法被发现

那张表里最有分量的是最后一行 —— 能发现它的门禁:0check:docs 比对的是「生成 vs 已提交」,而错误的标题是稳定的,所以它永远绿。Qa Protocolsrc/qa/ 建立那天起熬过了每一次重生成,直到 #4759 把 14 个标题并排印出来才被人眼看见。只加 QA 会修好这一个实例,把下一个 iam / rbac / sso 留给同样的沉默。

两个被证据否掉的选项,是这次没有变成镀金的原因

  • 查表 + 兜底:一无所获 —— 缺条目仍落回首字母大写、仍然沉默,数据只是搬了家。这个判断很关键,它正是「把配置抽出来」这种改动最常见的自欺形式。
  • src/*/index.ts 文件头推导:看着最优雅,实测不可行 —— 逐个读了 17 个:automation/data/identity/kernel 根本没有模块 doc block,security 的头是 "Permission Protocol Exports"(会把模块悄悄改名),contracts 是 "ObjectStack Contracts"。会同时制造改名与空标题两类新缺陷。读了全部 17 个再下结论,而不是抽查两个。

沿用旁边 CATEGORY_BLURBS 已在一个数据项上用了的惯例(blurbCoverage/formatBlurbCoverage,#4759),而不是发明新机制 —— 标题只是最后一个还在靠猜的按模块数据项。⛔ 没做成通用配置系统,边界守住了。

反向验证:方向比预测的更强,这才是真正买到的东西

  • (a) 删掉 qa 声明 → 生成器根本不生成,exit 1、一个字节都没写,并指名 + qa (directory exists, no title — add one line: qa: '...')。这是可见性属性的活证据,而且只有在「映射全覆盖、无兜底」时才可能出现 —— 换成「查表 + 兜底」,这一步会安静地产出 Qa Protocol。你用一次实测把上面那个被否掉的选项再否了一遍
  • (b) 还原推导形状 → gen:docs 绿色退出并把 Qa Protocol 发回四处,pin 4 红 8 绿,红的恰是三处产物断言 + 全树扫描。这个红绿切分本身就证明产物断言确实吃到生成器,而单测不够 —— 与 root-index.test.ts 立下的先例一致。

检查放在 resolveCategoryTitles()构造函数内部而不是旁边,使后来的调用方拿不到一张未经检查的 CATEGORIES —— 这一点也对:被替换掉的正是「没人必须显式退出的兜底」。

两个空字段(open_questions / out_of_scope_findings)你主动说明了为什么是空,并说清两个候选发现都是文档化的既定行为而非缺陷(contracts/ 未被管理、conversions/migrations 不产页,均在 build-docs.ts 自己的警告路径里写明,#4723 重写过)。查了再说「没有」,和没查就留空,是两回事。

本单落地后解锁 #6225 / #6226(同 format-type.ts + references 重生成),两者可考虑合并派发以省一次重生成。


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs-gen: getCategoryTitle() 只给 UI/AI/API 大写,qa 渲染成 "Qa Protocol"(参考页标题 + meta.json + 根索引导航三处)

2 participants

@os-zhuang@claude