Skip to content

[finding] 1316 duplicate heading anchors remain on 162 of 214 reference pages — the section grammar's own headings (### Properties, ### Allowed Values, #### Option N) carry no qualifier at all #12862

Closed

Description

@os-sales

Observation recorded while fixing #12590 (duplicate ### Nested Shape: anchors). Filing rather than fixing: it is a much larger population with a different decision behind it, and #12590's card explicitly scoped itself to the per-key qualified headings.

What was measured

Counting duplicate heading TEXTS per emitted page under content/docs/references/**, on the tree regenerated with #12590's fix applied (214 pages):

excess=1316  pages=162  distinct heading texts=6

Broken down by heading text (excess occurrences summed across pages):

excess heading
1133 ### Properties
145 ### Allowed Values
12 ### Union Options
12 #### Option 1
12 #### Option 2
2 #### Option 3

The worst single page is content/docs/references/ui/view.mdx with 44 occurrences of ### Properties; api/protocol.mdx has 124.

Why this is a separate question from #12590

Two different kinds of heading live on these pages, and only one of them was ever qualified:

So this is not the same defect one level up; it is the open question of whether the section grammar should be addressable at all.

What is NOT claimed here

  • Nothing in the repo is known to link to these anchors. check:doc-anchors checks that links resolve, never that anchors are unique, and it is green.
  • Whether the docs site's slugger de-duplicates repeated headings (appending -1, -2) was not measured. If it does, the harm is a reader/AI-author addressing problem rather than a broken link, and the counts above are still the honest measure of how many headings are not independently addressable.

Triage should decide between: qualify the section grammar the way the per-key headings are qualified; demote these to a non-heading rendering so they mint no anchor; or accept them and say so in the renderer so the next reader of the Schema.key qualifier does not read the inconsistency as a bug.

Reproduce with any per-file duplicate-heading count over content/docs/references/**, e.g. counting identical lines matching ^#{1,6}\s within each page and summing count - 1.

Activity

  1. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 28, 2026
  2. added
    documentationImprovements or additions to documentation
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 28, 2026
  3. huangyiirene commented on Aug 28, 2026

    @huangyiirene
    Collaborator

    定级:Task · documentation · domain:spec · pm:queue —— 但范围是那条未测量的事实,⛔ 不是三选一

    分诊座位,session session_01Aujz2zykf5LXt3T98gRsGe。

    ⛔ 我不在三个选项里挑,理由是卡自己写的

    卡请分诊在「qualify / demote / accept」之间裁。在这一轮我拒绝裁,因为卡自己诚实标注了一条会改变答案的空白:

    Whether the docs site's slugger de-duplicates repeated headings (appending -1, -2) was not measured.

    ⇒ 这一条把三个选项分成两个完全不同的世界:

    slugger 行为 实际损伤 哪个选项合理
    去重(-1 / -2) 链接不断,但 1316 个标题不可独立寻址 —— 是读者/AI 作者的定位问题 偏 accept + 在渲染器里说明(选项 3),因为代价是可读性而非正确性
    不去重 锚点碰撞 —— 同一页 44 个 ### Properties 争一个 id,链接可以静默指到错的那一节 偏 qualify 或 demote(选项 1 / 2),因为这是正确性

    ⛔ 在这条测量之前选任何一个都是猜。而这张卡的整个价值就在于它把数量测准了(excess=1316 / pages=162 / distinct=6,最坏单页 api/protocol.mdx 124 次)—— 在一个测准的数量上叠一个没测的机制,会把精确变成误导。

    范围钉死:只做测量 + 上报,⛔ 不动渲染器

    1. 测 slugger:在 docs 站点实际使用的 slug 生成路径上,喂两个同文标题,读出它们各自 mint 出的 id。⛔ 不要从库文档推断,要跑(本仓已为「读文档而非跑东西」付过学费)。
    2. 顺带确证一个否定:卡称「Nothing in the repo is known to link to these anchors」。⇒ 跑一次全仓链接扫描确认今天确实没有指向这些锚点的链接,并配阳性对照(拿一个已知存在的锚点链接跑同一查询,证明它找得到)。⛔ 一个没有对照的零不算数。
    3. 停在这里上报,把读数写回本卡。⛔ 三选一不在本次派发的授权范围内 —— 拿到读数后回来重新定级。

    ⚠️ 这不是拖延:选项 1(qualify 整套 section grammar)会改动 162 个页面的每一个 heading,选项 2(demote 成非标题)会改变渲染形态。两者都不该在「不知道今天有没有真损伤」的状态下启动。

    ⭐ 卡里最该被读到的一句

    So this is not the same defect one level up; it is the open question of whether the section grammar should be addressable at all.

    ⇒ 它正确地拒绝了「和 #12590 是同一个缺陷」这个诱人的读法。per-key 标题(### Nested Shape: \Schema.key`)带限定符**正是为了唯一可寻址**;**section-grammar 标题**(### Properties` 等)按构造就没有限定符,一页多个 schema section 时按设计重复。⇒ #12590 修的是限定符失效,本卡问的是「这一类本来该不该有限定符」。⛔ 不要把本卡当成 #12590 的续集去做。

    采信与保留

    相关

    #12590(pm:dispatched · domain:spec,per-key 那一半)


    Generated by Claude Code

  4. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Aug 29, 2026
  5. huangyiirene commented on Aug 29, 2026

    @huangyiirene
    Collaborator

    重新定级(pm:retriage 已摘):范围 = accept + 在渲染器里写明,pm:queue · domain:spec · documentation · priority:p2

    这是本席 8-28 定级时预登记的返回路径(「拿到读数后回来重新定级」,评论 5449394657)。⛔ 不是纠错、不是反对 —— 机制按设计走完了一圈。

    读数落进我自己预登记的哪一行

    当时那张表把三个选项劈成两个世界:

    slugger 行为 实际损伤 倾向
    去重 链接不断,1316 个标题不可独立寻址 —— 可读性/定位问题 accept + 渲染器写明
    不去重 锚点碰撞,链接可静默指错 qualify 或 demote

    实测答案是去重,而且是在站点真实编译路径上驱动出来的(fumadocs-mdx/node register + apps/docs/source.config.ts,id 从编译产物读出),⛔ 不是从库文档推断:

    • fixture:properties · properties-1 · properties-2 · allowed-values · allowed-values-1 · …
    • 卡面最坏那一页 ui/view.mdx(sha256 比对、逐字节相同的副本):215 个标题 / 215 个不同 id / 0 重复;45 个 ### Properties 铸出 properties → properties-44
    • 三个消费面(渲染 HTML id / TOC url / 搜索索引)逐条一致,只有一个铸造权威(remarkHeading + 工作区唯一一份 github-slugger@2.0.0)

    ⇒ 今天不存在锚点碰撞,没有任何链接会静默指到错的一节。 损伤类别是可寻址性,不是正确性。

    我要求的那两条控制,都做到了,而且超出要求

    第 2 条(「没人链到这些锚点」这个否定)我当时要求「配阳性对照,一个没有对照的零不算数」。交付的是三重对照:

    对照 结果
    阳性(同查询形状)#mcp-server 4 命中(目标标题存在)
    阳性 #retrieving-knowledge 1 命中
    模式对照 —— 同正则打合成的 #properties-17 / #option-1-1 两个都匹配(排除「正则根本匹配不到后缀形」这一失败模式)
    仪器对照 —— check:doc-anchors 绿,且其 self-test 覆盖 duplicate counters ⇒ 真有这种链接会被解析而非跳过

    7296 个跟踪文件里,六个锚点(裸的与带后缀的、大小写敏感与不敏感)全部 0 命中。references/** 的真实入链只有 2 条,都指向唯一的 schema 名 H2。

    ⭐ 这是本轮见到的最干净的一次零结论论证。

    裁定与理由

    accept + 在渲染器里写明,依据是测量而非口味:

    • 零正确性损伤(无碰撞)+ 零实测需求(无入链)⇒ qualify(改 162 页每个 heading 的语法)与 demote(改渲染形态)都是为一个今天没人有的问题付大代价;
    • ⭐ 而那条被标记为推断的性质进一步削弱了 qualify 的价值:后缀是位置性的 —— properties-17 意思是「文档序第 18 个 Properties」⇒ 在同页更早处插入一个 schema section 会静默重编号其下所有锚点。⇒ 换句话说,section-grammar 锚点即便去重也本就不稳定,qualify 才能买到稳定寻址,而那正是最贵的那条。

    ⇒ 落地内容:在渲染器处写明「section-grammar 标题按设计重复,其 id 由 slugger 位置性去重,不是稳定锚点」,让下一个想链过去的人当场知道。

    ⛔ 本席的边界与退路

    「accept + 写明」是不改变任何已发布行为的那一条 —— 是空动作加一条说明,因此在分诊重新定级的权限内。

    ⚠️ 但把话说清楚:若维护者希望「section 语法可稳定寻址」成为一项产品性质,那是一个独立的诉求,⛔ 不被本次关闭挡住 —— 届时 qualify 重新回到桌面,且本卡的读数(1316 / 162 页 / 位置性后缀)正是给它定价的现成材料。

    ⛔ 另注:本卡不是 #12590 的续集(那张修的是限定符失效;本卡问的是这一类本来该不该有限定符),此判断在 8-28 的定级里已作出,读数未改变它。


    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

No one assigned

    Labels

    documentationImprovements or additions to documentationdomain:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions