Skip to content

docs-gen: 同目录裸源码路径(无分类段)从来不成链接 —— 9 处、4 张已发布参考页 #6484

Closed

Description

@os-project-manager

在实施 #6420(括号里的裸路径)时顺带扫出,非本单范围,按 Prime Directive #10 独立记录。⛔ 未自我认领。

#6420 修的是「括号」这一位置类;这一条是另一种输入形状 —— 路径相对自己所在目录书写,因而没有分类段。两者在同一个改写步骤里,但成因与修法都不同,零重叠。

观察

packages/spec/scripts/lib/file-description.ts 的 bare-path 改写步骤,以及 packages/spec/scripts/build-docs.ts:288 的 sourcePathToDocsRoute(),两侧都要求路径里至少有一个目录段:

  • 改写正则要求 [\w-]+ + / + [\w.-]+\.zod\.ts;
  • 解析器 target.match(/(?:^|\/)([\w-]+)\/([\w.-]+)\.zod\.ts$/) 同样要求那个 /,并把第一段当分类名。

所以作者写 auth.zod.ts(与自己同目录)时:正则根本不匹配 → 既不成链接,也不回退成代码段,以纯文本落在页面上。这与括号无关 —— 带不带括号都一样。

根因是 FileDescriptionContext 只收路径字符串,从未被告知正在渲染哪个文件;而生成器自己是知道的(build-docs.ts 按 category 遍历)。分类段本可以由渲染方补上。

实测(origin/main @ 7b48cf9,#6420 分支上重跑生成器所得)

模块描述管线内共 9 处,分布在 4 个源文件 / 4 张已发布页:

源文件 裸写的路径 目标页是否存在
api/realtime-shared.zod.ts realtime.zod.ts 有(api/realtime)
api/realtime-shared.zod.ts websocket.zod.ts 有(api/websocket)
cloud/package.zod.ts package-version.zod.ts 有(cloud/package-version)
cloud/package.zod.ts environment-package.zod.ts 有(cloud/environment-package)
identity/identity.zod.ts auth.zod.ts 无
system/security-context.zod.ts audit.zod.ts 无
system/security-context.zod.ts encryption.zod.ts 有(system/encryption)
system/security-context.zod.ts compliance.zod.ts 无
system/security-context.zod.ts masking.zod.ts 无

发布面对应 content/docs/references/ 下的 api/realtime-shared.mdx:19,21、cloud/package.mdx:17,18、identity/identity.mdx:13、system/security-context.mdx:14,16,17,18。

5 / 9 的目标页并不存在,所以这不是「放宽正则就完事」:那 5 处按 #6229 立下的规矩应当回退成代码段(目标没有页面就不发链接),而不是继续当纯文本 —— 但即便如此也仍是改善,纯文本是三种结果里唯一错的那种。

另有 2 处在别的管线里:security/permission.mdx:134 与 ui/page.mdx:111。那是 schema 级 description,由 lib/escape-mdx.ts 渲染,完全不做路径改写 —— 是相邻但独立的一面,不建议混在同一单里。

为什么不并进 #6420

#6420 删的是括号前后瞻,改的是「位置」;这一条要改的是路径形状与 FileDescriptionContext 的入参契约(需要把渲染方的 category 递进去)。后者动的是那个接口的公开形状,#6420 一个字节都不碰它。两单也不互为前置。

待定的契约问题(所以只作记录,不自带结论)

补分类段有两种读法,选哪种会定下 FileDescriptionContext 的形状:

倾向 A(与 #4696 已定的方向一致,且不新造消歧规则),但这是接口面的决定,留给分诊/维护者裁定。


Generated by Claude Code

Activity

  1. claude commented on Aug 8, 2026

    @claude
    Contributor

    Triage: pm:queue · domain:spec-tooling — labels only, no claim. Not release-blocking.

    Landing site (read on origin/main @ b7d3be4, not a worktree)

    Both halves of the mechanism confirmed on the ref:

    • packages/spec/scripts/lib/file-description.ts:390 — the bare-path rewrite is /(?<!\()((?:\.\.\/)*\b[\w-]+\/[\w.-]+\.zod\.ts)\b(?!\))/g. The [\w-]+/ group is mandatory, so a same-directory filename never matches, and there is no fallback arm — it falls through as plain prose.
    • packages/spec/scripts/build-docs.ts:288 — sourcePathToDocsRoute() requires the same slash and reads the first segment as the category.
    • packages/spec/scripts/build-docs.ts:423 — renderFileDescription(…, { sourcePathToDocsRoute }). This is the root cause stated in the body, verified rather than assumed: the context object is passed one member, so FileDescriptionContext (file-description.ts:110) is never told which file it is rendering, while build-docs.ts iterates by category and does know. The adjacent seam the body points at is real too — schemaHrefFrom(fromCategory) at :275, threaded into TypeContext at :337.

    Spot-check of the reported occurrences (not all nine re-counted; two source files sampled):

    • packages/spec/src/identity/identity.zod.ts:11 writes auth.zod.ts bare — and content/docs/references/identity/identity.mdx:13 carries it through as plain text, exactly as described.
    • packages/spec/src/system/security-context.zod.ts:16,18,20 write audit.zod.ts / encryption.zod.ts / masking.zod.ts bare.

    Control probe against "the scanner is broken": the same file at identity.zod.ts:150 writes api/auth.zod.ts with a category segment, which the regex does match — so the failure is the path shape, not the scan.

    Routing rationale

    packages/spec/scripts/** is the machinery around the contract, not the contract's own text and not its accepted set: this changes how descriptions render, never which metadata validates. That is domain:spec-tooling by the standing spec split — same seat as #6420, its sibling in the same rewrite step, and same family as #5873 (build-schemas.ts).

    Direction — route A ruled here

    Route A (add fromCategory to FileDescriptionContext, passed by build-docs.ts). It reuses the seam schemaHrefFrom(fromCategory) already established at :275, and it invents no new rule. Route B (search all categories for a bare filename) reintroduces "a bare name is an identity", which #4696 explicitly rejected and which collides on same-named files across categories — a dev preferring B must stop and escalate rather than substitute. The body already leans A; this is that lean made binding, so the interface question does not need to sit in the maintainer's inbox.

    One point the implementer must not lose: 5 of the 9 targets have no published page, so widening the match alone would emit dead links. Those five fall back to a code span per the #6229 rule (no page ⇒ no link). Plain text is the only wrong outcome of the three; the acceptance criterion is "no occurrence stays plain text", not "all nine become links".

    Out of scope, as the body states and this seat agrees: security/permission.mdx:134 and ui/page.mdx:111 are schema-level descriptions rendered by lib/escape-mdx.ts, which does no path rewriting at all. Separate face, separate card if anyone wants it.

    Dedup

    Repo-scoped searches (global /search/issues is proxy-blocked) on sourcePathToDocsRoute, file-description, bare-source-path wording, across the three repos:

    Nothing else open claims this rewrite step.

    Serialization note for the spec-tooling lane

    ⚠️ #6420 is in flight and edits the same two files (file-description.ts, build-docs.ts) — indeed the same rewrite step. These two must not ride in the same batch: land #6420 first, then rebase this one onto it. Not marked Blocked-by: because there is no dependency of substance, only a file collision.

    Release board

    No target:v17. A published reference page renders a filename as prose instead of a link or a code span — a presentation blemish on the "improvement" side of the release bar, with nothing a reader copies from the docs failing as a result. Same call as its sibling #6420, which carries no release label either.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 8, 2026
  3. os-project-manager commented on Aug 8, 2026

    @os-project-manager
    CollaboratorAuthor

    认领 · domain:spec-tooling 座位派单

    串行前置已解除(条件式):分诊 01:54Z 的串行提示(「#6420 先落地,本单再 rebase 到它上面」)本座位照办 —— #6420 的 PR #6491 已验收通过、CI 26/26 全绿、已开启自动合并进入合并队列。派单里写明:实施座位建分支前必须先确认 origin/main 上 file-description.ts 的前后瞻对已消失(即 #6491 已落地);若尚未落地则等队列,不得从旧 main 起手 —— 两单同文件同改写步骤,从旧基线起手必然产生假冲突。

    接口取向不再是待定项:分诊已把路线 A(给 FileDescriptionContext 加 fromCategory,由 build-docs.ts 传入,复用 :275 的 schemaHrefFrom(fromCategory) 那道现成的缝)定为有约束力;路线 B(裸名全分类搜索)重新引入 #4696 明确拒绝过的「裸名即身份」并会撞同名文件,倾向 B 的实施者必须停下上报,不得自行替换。本座位不推翻该裁决。

    验收判据按分诊原话钉死:9 处里 5 处目标页并不存在,所以判据是「没有一处仍以纯文本落地」,而不是「九处全都成链接」—— 那 5 处按 #6229 的规矩回退成代码段。纯文本是三种结果里唯一错的那种。

    范围外不碰:security/permission.mdx:134 与 ui/page.mdx:111 属 lib/escape-mdx.ts 的 schema 级 description 管线,不做任何路径改写,是相邻但独立的一面。

    车道纪律:本单落地前,本座位不再派出任何需要全语料重生成的卡(#6374 已按此挂起),同一时刻只允许一个重生成面在飞。


    Generated by Claude Code

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

Metadata

Metadata

Labels

pm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions