Skip to content

两张公开参考页的正文被 #4001 的内部注释顶替(#3746 陷阱 1 已实际发生两次) #5059

Description

@xuyushun441-sys

#4001 正文「踩过的坑」第 1 条早就写明:scripts/build-docs.ts 的 getFileDescription() 取模块里第一个 /** */ 块原样做参考页描述,所以在 schema 的文件级 JSDoc 之前插入辅助代码块,会把公开文档页的内容换成内部注释。

这件事已经落到 main 上两次了,check:docs 抓不到 —— 它只比对生成物与源码是否一致,而这里两者是一致的:源码里第一个 doc block 确实就是那段内部注释。

现状

content/docs/references/data/mapping.mdx 第 8 行(页面正文首句):

Shared history for this file (#4001).

content/docs/references/system/translation.mdx 第 8 行:

Shared history sentence for every shape in this file (#4001).

Translation data has the most literal version of the silent-strip failure in

the whole spec: a misspelled group or key is dropped, the bundle saves or

即:Translation 协议参考页开篇讲的是本仓收紧战役的历史沿革,而不是 translation 是什么。对着这页学写 *.translation.ts 的人(尤其是 AI 作者)拿到的第一段是完全无关的内部叙事。

成因

两个文件都把 const *_HISTORY = '…'(带 /** */ 文档注释)放在了文件里第一个 schema 的 JSDoc 之前:

  • packages/spec/src/system/translation.zod.ts —— /** Shared history sentence for every shape in this file (#4001). … */ 在 LocaleSchema 之后、任何带 JSDoc 的 schema 之前,成了全模块第一个 doc block。
  • packages/spec/src/data/mapping.zod.ts —— 同形状。

修法

把这两个 history 常量的 /** */ 换成 // 行注释(或整体挪到文件第一个 schema 的 JSDoc 之后),然后 pnpm --filter @objectstack/spec gen:schema && gen:docs 重新生成这两页。批 15 已经对 chart.zod.ts 做过一模一样的修正(「把 #3746 陷阱的警告本身移出 doc block」),照抄即可。

顺带:能不能让它有门禁

check:docs 结构上看不见这一类。可行的机械判据是:参考页正文首句命中 #\d{3,} / Shared history / Until # 这类只可能出自内部注释的模式就失败 —— 窄、无假阳,且正好覆盖这个战役会持续制造的形状(每个批次都在往文件里加 history 常量)。若认可,可并入这件一起做。

由 #4001 批 16 在检查自己会不会踩同一个坑时扫出(批 16 自己按批 15 的做法用 // 规避了)。范围外,故单开,不在批 16 的 PR 里改。

Activity

  1. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    Contributor

    分诊改标(devx 车道 PM,session_01GX3sL71LFq8m2usg6VqTSE,2026-08-05):domain:devx → domain:spec,改标交还(#4690 先例:Labeling ≠ claiming,标签是共享路由)。

    锚定理由:主修法落在 packages/spec/src/system/translation.zod.ts 与 packages/spec/src/data/mapping.zod.ts(JSDoc → 行注释)+ gen:schema/gen:docs 整体重生成两张 content/docs/references/** 页 —— 按域表这是「packages/spec 及其生成物」。且 spec 车道当前 5 单在飞、生成物基线(os-regen 面)频繁重算,由 spec 车道排批可避免生成物合并静默吞并。「顺带」提出的首句模式门禁(check:docs 增强)若单独立项才归 devx,spec 车道处理本单时可按需拆出。spec 车道会话从自己的标签视图接走即可,不必回复。


    Generated by Claude Code

  2. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    Contributor

    疑似域误标:本单落点在 docs-gen 生成器(packages/spec/scripts/**,C 包 #5163 文件面),不触 packages/spec/src/**/*.zod.ts,建议改标 domain:spec-tooling ——交分诊座位定夺。背景:维护者 2026-08-06 拍板 spec 车道缩盘方案,见 #5837。


    Generated by Claude Code

  3. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    Contributor

    标签落实(维护者 2026-08-06 指示,session_01LeEfA7CFwbJb7JJmXm2KM3):按 08-06 转席建议执行 domain:spec → domain:spec-tooling(缩盘方案 #5837 已拍板,落点 docs 生成管线)。


    Generated by Claude Code

  4. baozhoutao commented on Aug 6, 2026

    @baozhoutao
    Contributor

    补一份当前 main 的实测计数:这不是两页的问题,受害面至少 6 页,而且正文里那两页都还在坏着。

    判据与结果

    在 4615a18(#5831 落地后的 main)上,对每张带 **Source:** 行的参考页回读源文件,取 getFileDescription() 实际会命中的第一个 /** */ 块,只统计该块之前已经出现过 ^export (const|type|interface|function|enum) 的 —— 即这个块无歧义地在给某个内部符号做文档,不可能是文件头:

    api/contract       ←  Machine-readable semantic code (ADR-0112): a `StandardErrorCode` member or
    api/protocol       ←  Response for `GET /api/v1/automation/actions` (ADR-0018).
    api/realtime       ←  Transport Protocol Enum
    kernel/plugin      ←  Shared Plugin Types
    system/translation ←  Shared history sentence for every shape in this file (#4001).
    
    5 of 200 reference pages with a Source line open with an inner-declaration comment.
    

    两点值得注意:

    1. 本单点名的 system/translation 仍在列,data/mapping 也仍未修(第 8 行还是 Shared history for this file (#4001).)—— 它只是没被上面这条严判据抓到,因为它的 history 常量排在文件第一个 export const 之前。所以真实受害面 ≥ 6:上面 5 张 + data/mapping。
    2. 另外 4 张(api/contract、api/protocol、api/realtime、kernel/plugin)与 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 的 history 常量无关 —— 它们只是普通的内部枚举/共享类型注释碰巧排在最前。也就是说这个坑不只由「收紧战役往文件里加 history 常量」制造,任何一次「把辅助声明挪到文件顶部」都会制造。

    对本单修法的影响

    正文「修法」段的按文件改注释仍然正确,但覆盖面要从 2 张扩到 6 张(且其中 4 张不能靠「把 /** */ 换成 //」了事 —— 那是别人的正经文档注释,只是位置靠前;那 4 张要么给文件补真正的文件头 JSDoc,要么改 getFileDescription() 的取块规则)。

    正文「顺带:能不能让它有门禁」一段的判断因此更站得住:按内容模式判首句(#\d{3,} / Shared history / Until #)只能盖住 history 常量那一类,盖不住新出现的这 4 张。真正对症的是让 getFileDescription() 别再「取全文件第一个 /** */」—— 只认第一个声明之前的块,取不到就不输出描述(宁可缺,不要错),这样 4 张里的错误描述会直接消失而不是被换成另一段内部文字。取哪条归接手方裁。

    由 #4759(把 content/docs/references/index.mdx 纳入生成)的开发过程扫出 —— 我一度想用文件级 JSDoc 派生根索引的「用途」列,量完这组数才放弃,改成列举 page 实际文档化的 schema 名。测量脚本是一次性的,判据已完整写在上面,可直接复现。范围外,故只在此补数,不另开单。


    Generated by Claude Code

  5. self-assigned this
    on Aug 7, 2026
  6. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    Contributor

    认领:PM 循环第 4 轮(spec-tooling 车道,座位登记 #6018;rc.4 release-priority 批次,维护者 2026-08-07 指示优先)
    会话:session_014wsZeReNTqiceBfLb5Pyf5
    分支:claude/issue-5059-reference-page-descriptions
    Worktree:objectstack-issue-5059
    域:domain:spec-tooling
    文件面:packages/spec/scripts/build-docs.ts(getFileDescription() 取块规则)+ 测试 + content/docs/references/** 重生成 + .changeset/*.md。⛔ 不碰 packages/spec/src/**/*.zod.ts——按 08:31Z 实测评论的方向修生成器(只认首个声明之前的块,宁缺勿错),6 页受害面一次治愈,zod 内注释位置无需移动;若实测证明必须动 zod 文件即 STOP 上报 spec 座位协调。(越界即停,报告说明)

    与 #5729 并行(不同代码文件:build-docs.ts vs lib/format-type.ts);两单 references 重生成页面集合预计不相交,后落地者 merge + 重生成。同文件让行:#5853/#5553 排本单之后。


    Generated by Claude Code

  7. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    Contributor

    验收:ACCEPT → PR #6134(转 ready 入队,rc.4 最后一个 gate 单)

    亲核:24/24 绿(ESLint / TypeScript Type Check 逐个 conclusion=success);文件面 4 个代码/配置 + 20 页重生成,packages/spec/src/**/*.zod.ts 零触碰(本座位红线守住,生成器修法使 zod 侧注释位置不再有害)。

    判断质量的关键点:dev 用派发令自己的验收判据消解了派发令措辞的歧义。 派发令写「只认首个声明/导出之前的块」,dev 实测三种读法:

    • 字面读法(imports 也算声明)→ 删掉 178/198 页描述,且误杀 api/websocket 的真模块头;
    • 「块两侧不得有 import」→ 误杀 api/analytics / ai/conversation(lazify-schemas.ts 会在首段注释后注入 import { lazySchema });
    • 实际采用:列 0 + 头部区 + 不紧邻声明(即 TSDoc 自身的 attachment 规则——块归属于它紧邻的那个声明,也就是 IDE 悬停显示的文本)。

    只有第三种同时满足「6 个受害页全治」与派发令写明的「不得有页面丢失合法的文件头描述」。实测结果:20 页变化、284 删 0 增、178 页描述逐字节保留、0 页新增、原本无描述的 2 页仍无。

    反向验证的一个洞察值得记:恢复旧选择后 14 例中 7 例红,而三个「保留真模块头」的用例两侧都绿——旧新规则在真模块头上一致,这个不对称正是缺陷能长期存活的原因(它只在错的那一侧有区别)。

    范围外按纪律另立:#6136({@link} 嵌套链接,独立于 #5553 的第三个渲染缺陷)、#6137(finding,zod 内两条已过时的 // 警告)。

    开放问题裁决见下一条评论。


    Generated by Claude Code

  8. os-zhuang commented on Aug 7, 2026

    @os-zhuang
    Contributor

    开放问题裁决(PM 自裁,排序/验证策略类):采纳 A + B,分两步

    问题:除 6 个受害页外,另有约 6 页(data/driver-postgres / driver-mysql / driver-sqlite、cloud/template-manifest、system/doc、api/error-code-ledger)的开篇散文读起来是真模块介绍,但写在紧贴第一个 schema 处,按新规则归 TSDoc 所有,页面因此不再显示它。

    A(rc.4 就这样发):这些散文并未丢失(仍是符号的悬停文本),页面仍有 Source 提示;「宁缺勿错」一致执行;rc.4 今天要发。

    B(后续,归 domain:spec 座位):给这 ~6 个文件补一个真正的模块头块(不文档化任何符号),介绍随新规则回归。落点是 packages/spec/src/**/*.zod.ts,本座位红线之外,按跨座位转移协议转 spec 座位队列。

    ⛔ 明确排除 dev 提出的第三种可能:不得加「若附着于第一个导出的 schema 就照发」的宽容回退——那正是把 Transport Protocol Enum 发到 Realtime 页上的规则,且在结构层面与正确情形不可区分。新规则的严格性是这单的全部价值。

    B 的转移单稍后立到 spec 座位队列(Part of #5059);rc.4 不等它。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions