lint-nav-reachability: 补一条「同束内页面必须至少被一个真实链接引用」检查(F318 跟进)
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 1h 7m
- Merged PRs (30d)
- 969
Description
## 背景
F318(#318)修的是:`apps/web/app/tpl/designer/page.tsx` 是蓝本设计器的真实挂载点,但全仓零 ``/`router.push` 指向它——左侧导航和「编辑设计」CTA 都还接在 `/tpl?screen=designer` 这个原型态上。这个漂移之所以没被拦住,是因为现有 `.harness/scripts/lint-nav-reachability.mjs` 只检查**导航树 → 束路由**这一层(`navigation.ts` 里的 href 能不能解析到束的现行 `page.tsx`),完全不看**页面内部**渲染的是哪个子组件、也不看**某个 `page.tsx` 文件本身是否被任何组件内部的 CTA 引用过**。
`/tpl/designer/page.tsx` 是一个真实存在、解析得到、甚至被写进 `nav-reachability.config.json`/`ui-material-map.json` 的合法路由(如果它在配置里的话——需要核实),所以现有五条判定全部通过,问题却依然存在:它是「页面内部渲染分叉出的孤儿页」,不是「导航树缺项」。
## 建议方向(原 #318 里提出,评估后判断是更大的改动,故拆出来单独跟踪)
给 `lint-nav-reachability.mjs`(或新脚本)加一条检查:
- 枚举 `apps/web/app/**/page.tsx`(排除 `(group)`/动态段的特殊情况);
- 对每个 page 路由,在 `apps/web/components/**` + `apps/web/app/**` 里 grep 是否有任何字符串字面量/模板字面量引用了这个路径(`href="..."`、`router.push("...")`、`redirect("...")` 等);
- 排除已知合法的「无内部引用」场景:根路由、通过 `navigation.ts` 直接可达的路由(不需要页面内部再引用一次)、显式标注为 deprecated-redirect 的页面(如 `/studio/interview`)。
## 为什么没在 #318 里顺手做
评估后发现这条检查比 F318 本身的路由修复复杂得多,风险点包括:
- 动态段 `[id]`/catch-all 路由的匹配需要正则而非字面量比较,容易漏报或误报;
- 有些页面故意只能通过 `redirect()` 到达(如 `/studio/interview`),不该算孤儿;
- 有些页面路由字符串是运行时拼出来的(模板字符串 + 变量),静态 grep 抓不到,会有噪音误报;
- 需要一份「排除清单」机制,否则会拦住大量本来就设计成「仅导航可达、无需内部再链接」的叶子页面。
在没有先想清楚排除规则和匹配算法之前贸然加门控,容易做出一个「一堆误报靠人肉豁免」的新版本——这正是仓库里反复出现「写完门控立刻造反证」的教训(见 workspacex-gate-counterproof-discipline 记忆)。所以按 #318 的原始建议,单独开一条 issue 来做,不在这次路由修复 PR 里塞。
## 验收方向(草案,非最终)
- 新增检查能在测试夹具里复现 F318 这个具体场景:一个真实存在、可解析的 `page.tsx`,但仓内没有任何组件对它的路径做字符串引用 → 报红。
- 至少覆盖一个"故意允许无内部引用"的豁免用例(如 deprecated-redirect 页面)不报红。
- 现有 `lint-nav-reachability.test.ts` 全部保持通过。
Contributor guide
No contributing guide indexed for this repository
Research direction
Read .harness/scripts/lint-nav-reachability.mjs and lint-nav-reachability.test.ts first, then inspect nav-reachability.config.json and ui-material-map.json. Use a test fixture for the F318 orphan-page case and a deprecated-redirect exemption. Done means the orphan is reported, the exemption is accepted, and the existing test suite remains passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- testing, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100