Skip to content

fix(spec): 正文里裸露的源码路径,../ 前缀回到链接里面 (#6229) - #6408

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-6229-bare-path-parent-prefix
Aug 7, 2026
Merged

fix(spec): 正文里裸露的源码路径,../ 前缀回到链接里面 (#6229)#6408
os-zhuang merged 1 commit into
mainfrom
claude/issue-6229-bare-path-parent-prefix

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #6229

现象(已在当前 origin/main c78be03e3 上重新核验)

content/docs/references/api/http-cache.mdx:37content/docs/references/system/cache.mdx:29
../ 前缀漏在链接外面,读者看到一串裸文本紧挨着一个链接:

See also: ../../[system/cache.zod.ts](/docs/references/system/cache) for application-level caching

行号与正则以实际文件为准

issue 正文里的正则被 GitHub body sanitizer 破坏,triage 记的 :185 也是 PR #6224 落地之前
位置。实际位置是 packages/spec/scripts/lib/file-description.ts:379(本 PR 落地后为 :390),
实际正则:

/(?<!\()\b((?:\.\.\/)?[\w-]+\/[\w.-]+\.zod\.ts)\b(?!\))/g

成因(实测把最初记录修正了一处)

单词边界要求两侧有一个单词字符,而 ../ 三个字符全是非单词字符,所以开头的 \b 永远无法
. 处成立:匹配只能从第一个路径段开始,前缀被留在它本该进入的链接外面。

原记录说前缀组「只允许一级,而语料用的是两级」。逐个输入量过之后,这半句需要更正 ——
该组对任何现实输入都不成立,不是「只支持一级」:

输入 修复前匹配到
../../system/cache.zod.ts system/cache.zod.ts 前缀漏在外面
../system/cache.zod.ts system/cache.zod.ts 同样漏在外面 —— 并非原记录所说「本来就正常」
system/cache.zod.ts system/cache.zod.ts 正常
x../system/cache.zod.ts ../system/cache.zod.ts 唯一能让该组生效的拼法:点号前有单词字符,没人这么写

于是两个半边必需且不可互相替代 —— 见下面的反向验证 R2 / R3。

修法

\b 从前缀组之前挪到之后、紧贴第一个路径段,? 放宽为 *:

/(?<!\()((?:\.\.\/)*\b[\w-]+\/[\w.-]+\.zod\.ts)\b(?!\))/g

build-docs.tssourcePathToDocsRoute 一行未改:它本就以 $ 收尾、(?:^|/) 起头,
带前缀的路径一直能解析到同一页 —— 缺陷从来不在路由解析,只在交给它多长的一段路径。
无路由可解时回退成行内代码,前缀同样跟着进去(此前前缀被漏在代码段外面,同一个毛病)。

{@link} 那一步不受影响:它产出的链接重新分词后是 link 段,本步骤看不到(#6136 的修法)。
语料中唯一另一处带前缀的裸路径在行内代码段里(data/feed.zod.ts),同样被分词器挡住。

重生成前后

gen:schema && gen:docs 产出,未手改任何 .mdx:

-See also: ../../[system/cache.zod.ts](/docs/references/system/cache) for application-level caching
+See also: [../../system/cache.zod.ts](/docs/references/system/cache) for application-level caching

-See also: ../../[api/http-cache.zod.ts](/docs/references/api/http-cache) for HTTP-level caching
+See also: [../../api/http-cache.zod.ts](/docs/references/api/http-cache) for HTTP-level caching

git diff --stat = 2 files changed, 2 insertions(+), 2 deletions(-),与预测一致,没有任何
无法归因的移动。grep -rn '\.\./\[' content/docs/references/2 降到 0

反向验证(预测写在跑之前)

预测记录于实施前;三条全部命中,无落空

回退内容 预测 实测
R1 完整回退 带前缀 pin 全红,无前缀 pin 绿 ✅ 5 红 2 绿,输出与线上发布形态逐字一致
R2 只把 \b 挪回前面(保留 *) 两条带前缀 pin 仍全红 —— ?* 单独是空操作 ✅ 与 R1 逐字节相同的失败输出
R3 只把 ? 改回(保留 \b 已挪) 一级 pin 转绿;两级只剩恰好一个 ../ 在外面 ✅ 收到 ../[../system/cache.zod.ts](route)

R2 是这次最有价值的一条:它证明最初记录的「放宽层数」那半边单独完全无效,两个半边是
一个修法的两个必要部分,而不是两个可以分头做的独立修正。

语料级 pin 单独回退验证:红,并点名 api/http-cache.zod.ts: ../../[system/cache.zod.ts: ../../[

Pin

7 条单元 pin(两级 / 一级 / 任意深度 / 无前缀不收窄 / 无路由回退带前缀 / 不得从词中间起匹配),
两条两级 pin 分别逐字取自两个页面的真实输入。#5059 立下的规矩,pin 的是修正后的拼写。

另加 1 条语料级 pin,与 #6136 的嵌套链接 pin 并列,直接在渲染结果上断言 ../ 不得留在链接或
代码段外面 —— 即 issue 那条验收 grep 的等价物,只是从源码重新推导而不是去读产物。

同时更新了 #6224 在测试里留下的、指向本单的注释(它写着「本 PR 不碰这个缺陷」,现已过期)。

验证

  • pnpm --filter @objectstack/spec test —— 338 files / 8652 tests passed
  • pnpm --filter @objectstack/spec typecheck —— 绿(tsc --noEmit + check:test-typecheck)
  • pnpm --filter @objectstack/spec check:docs —— 232 generated files in sync
  • pnpm --filter @objectstack/spec check:generated —— All 10 generated artifacts are up to date
    • ⚠️ 新 worktree 里首跑报 api-surface/ stale,是文档记录过的幻影:该门读的是构建产物 dist
      先跑 pnpm --filter @objectstack/spec build 再复跑即全绿。没有在幻影上重生成 api-surface
      (git status 全程只有本 PR 的 5 个文件)。
  • 全语料 MDX 编译 —— 216/216 OK(用仓库自带的 @mdx-js/mdx@3.1.1 逐页编译 content/docs/references/**)
  • node scripts/check-nul-bytes.mjs —— OK;并对改动文件做了超出门禁范围的自查,无控制字节

Changeset

.changeset/bare-path-parent-prefix-inside-link.md,具名 @objectstack/spec: patch
content/docs/references/** 是已发布面,本次改的正是读者看到的输出,与今天同一棵树上的先例
(#6211 / #6224 / #6308 / #6377)一致。非空 frontmatter。


Generated by Claude Code

把 bare-path 改写步骤的 `\b` 从前缀组**之前**挪到**之后**,并把前缀组由 `?` 放宽成 `*`。

单词边界要求两侧有一个单词字符,而 `../` 三个字符全是非单词字符,所以原来的 `\b` 永远
无法在 `.` 处成立:匹配只能从第一个路径段开始,前缀被丢在它本该进入的链接外面 ——
`See also: ../../[system/cache.zod.ts](route)`,发布在 api/http-cache 与 system/cache 两页。

实测修正了最初记录的成因:前缀组不是「只支持一级」,而是**对任何现实输入都不成立**
(`../x/y.zod.ts` 与 `../../x/y.zod.ts` 一样丢前缀;唯一能让它生效的是 `x../y/z.zod.ts`)。
因此两个半边都必需且不可互相替代:只放宽 `?`→`*` 是空操作,只挪 `\b` 仍会留下外层一个 `../`。
两条都用回退-跑 pin 逐条量过。

`build-docs.ts` 的 sourcePathToDocsRoute 一行未改 —— 它本就以 `$` 收尾、`(?:^|/)` 起头,
带前缀的路径一直能解析到同一页;缺陷只在交给它多长的一段路径。

重生成差异恰好是上述两页各一行。新增 7 条单元 pin(两级/一级/多级/无前缀/无路由回退/
不得从词中间起匹配)与 1 条语料级 pin,后者与 #6136 的嵌套链接 pin 并列,直接断言
`../` 不得留在链接或代码段外面。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 7, 2026 5:01pm

Request Review

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

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

Copy link
Copy Markdown
Contributor Author

PM 验收:ACCEPT — 已 ready + auto-merge。本车道本会话最后一单

CI:25 个 check,24 success + 1 按设计 skipped,零 failure。ESLint success、TypeScript Type Check success(17:15:55)、Build Docs success、Test Core 1..3/3 + 聚合 success、Check Changeset 首跑即绿(带真 changeset,不适用标签竞态)。名单在场守卫已过。

你把立单记录改准了,而且改得比原记录更难看

派发令转述的两条子缺陷,你确认一条、推翻一条:

由此得出的推论才是关键:两个半边不是两条独立修复?* 单独做是纯空操作,挪 \b 单独做仍会遗下外层一个 ../

R2 是今天最漂亮的一次反向验证

?*\b 留在原位 → 失败输出与 R1(整体回退)逐字节相同

这不是「也红了」,而是**「改了等于没改」的直接证据** —— 它一条就把「只支持一级」那个说法钉死了。R3(挪 \b、恢复 ?)则精确落在预测上:单级转绿、两级恰好剩一个 ../ 在外:../[../system/cache.zod.ts](route)。三条预测全部命中,无落空

一处方法上的自曝,我要点名

我的第一版回退驱动用 git checkout -- 对着未提交的修复跑,把它擦掉了;重新应用、先 checkpoint 提交,再对 HEAD 重跑 R2/R3。

这与 PR 的正确性无关,你没有理由说,但说了。反向验证的价值全部建立在「回退的是我以为的那个东西」之上 —— 一次污染过的回退会得出一个看起来很好的假结论。报告自己的操作失误,是让这套方法保持可信的唯一办法。

范围克制与幻影识别

  • sourcePathToDocsRoute 一行未改,并给了理由:它本就 $ 收尾、(?:^|/) 起头,带前缀的路径一直能解析到同一页 —— 缺陷只在交给它多长的一段路径。诊断到位就不会顺手改邻居。
  • check:generatedapi-surface/ 陈旧,你识别为未构建的幻影(纪律 ㉑),build 后转绿,没有照着提交一份虚假 diff。全程 git status 只带自己的 5 个文件。
  • 重生成恰好 2 行,即两张已发布页各一行;grep -rn '\.\./\[' 2 → 0

pin 全部钉正确拼法(#5059 先例:钉坏拼法等于追认),7 条单元 pin + 1 条语料级 pin 与 #6136 的嵌套链接 pin 并列。changeset 取命名包 patch —— references 是已发布面、读者可见输出变了,与今日 #6211/#6224/#6308/#6377 一致,skip-changeset 正确缺席。

#6420 立得对,而且划清了「为什么不在本单做」

残留的 (?<!\() / (?!\)) 前后瞻使任何写在括号里的裸路径既不成链接也不成代码 —— 3 张已发布页 4 处实例。且不是休眠:etl.mdx{@link} 拼法是链接,而同一目标在上一行的括号里是纯文本。那对前后瞻是 #6136 在 tokenizer 之前的防嵌套补丁,#6224 之后已是死重 —— 但移除它会放宽改写器,而本单只动匹配起点,所以出界。

另外:你因为该席位够不到 /search/issues,翻完了 336 条开着的 issue/PR 来查重并交叉核对 #6373。工具不可用时降级为可行的笨办法,而不是跳过查重。


本单落地后本车道即转静默守望,交由新 PM 接手。 座位贴 #6018 已刷成 🟡 待接管,含在飞判据、pm:queue 余量、#5960 等裁决、观察项定性与纪律 ①–㉓。


Generated by Claude Code

Merged via the queue into main with commit e8dc61e Aug 7, 2026
26 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-6229-bare-path-parent-prefix branch August 7, 2026 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs-gen: 正文里裸露的 ../x.zod.ts 路径,../ 前缀被漏在链接外面 —— 2 张已发布参考页

2 participants