Skip to content

[Decision] Should check-doc-links learn to judge links in source files at all? The measurement rules out the shape triage imagined #6430

Description

@os-warren

Filed by the domain:devx @ objectui execution seat (#5748), PM session session_012CZgmFFzqA9cX8tBMhvpFe, R34. ⛔ I do not set domain:* or type labels — routing is the triage seat's. needs-user-decision because the answer is a capability addition with a measured cost, not a fix.

⚠️This card exists because #6342's implementation returned premise_still_valid: false. The measured facts contradict the direction triage ruled, so I am filing the conflict rather than executing a ruling the measurement refutes. The hand repairs #6342 also called for are not blocked by this and ship in PR #6428.

The census that changed the question

Repo-wide, github.com/objectstack-ai/objectui/(blob|tree)/main/… occurs 138 times:

wherecount
.md / .mdx — already in the gate's population117
outside it (.ts 18, .mjs 2, .tsx 1)21
— of those, the gate's own deliberately-dead fixtures16
— the literal ellipsis in the gate's own hint text2
— genuine authored links in product source3
— of those, already dead2

Both dead ones named MIGRATION_GUIDE.md, deleted in 8c5d20455. They are repaired by hand in PR #6428.

⭐ The finding that rules out the ruled direction

Triage's charter was "Fix is population widening in the gate: admit doc-link-bearing comments in source files."Population widening alone is a measured no-op for this defect shape.

The real mechanism: inside the gate's current markdown population, 116 of 116 self-repo blob/tree URLs are written [x](y) and 0 are bare. In source files, 3 of 3 are bare. The two populations spell links differently; the extension filter was never the only thing in the way.

Proven, not argued — a faithful simulator (same stripCode(), same regex, same self-repo arm) over a source file carrying both spellings reports the markdown one and ⛔ not the bare one, while the same simulator reports 4 findings on the gate's own fixture file, so it demonstrably works.

The noise measurement, which prices option B

Pointing the existing pipeline at 3,764 source files extracts 257 matches and would emit 194 findings — none a genuine defect:

  • 135 of 194 come from the gate's own test file — a widened gate's first act is to fail on its own fixtures;
  • 48 of the 257 extractions are not links at all, but TypeScript that matches the regex: 'n.title, { description: n.message }', 'msg', a regex character class, 'javascript:alert(1'.

⚠️ And the natural defence does not work here: js-comment-mask.mjs keeps comments only, while both real dead links lived in string literals. ⭐ The false-positive protection is mutually exclusive with the defect.

⛔ No baseline is proposed, and the ratchet instruction's precondition is not met: the flood is test fixtures and non-links, not historical debt. Freezing 194 fixture strings would not be a ratchet.

Options

A — Do nothing further. 2 dead links repaired by hand (PR #6428); 3 genuine self-repo URLs exist in source repo-wide, so accrual is roughly one per several thousand files. Close #6342 on the census.

B — Build the real capability. Widen the population plus a new bare-URL extractor plus a comment/string discipline. Cost: 194 findings on day one, ~135 of them the gate's own fixtures needing explicit exclusion, plus a new false-positive class — and comment-only masking would still miss the exact defect that motivated the card.

C — Narrow variant. A bare-URL-only self-repo check over source files, no markdown-link parsing at all, so none of the 194 noise. Population: the 3 genuine URLs plus the 2 in the gate's own hint text. Signal 3, noise 2, both trivially excludable.

四轴分析

① 实际业务需求. 实测债务是 2 条,已用手修完,且积累速率约为每几千个文件一条。B 为了抓一个规模为 2 的缺陷类,第一天要引入 194 条待分诊结果 —— 其中 135 条是闸门自己的 fixture。⭐ 而 B 的天然防误报手段(只保留注释)与缺陷本身互斥:两条真死链都活在字符串字面量里。这一轴强烈指向 A。

② 项目长远合理性. 北极星是 declared = enforced。⚠️ 但这里没有任何"声明"被违背 —— 闸门从未宣称覆盖源码文件,它的 SCAN_ROOTS 和扩展名过滤器都是明写的。所以 A 不制造"声明与执行不一致"。反过来,B 会让闸门开始解析源码,这是它运行时和误报面的实质改变,而不是一行正则。C 是唯一在不改变闸门性质的前提下拿到能力的形状。

③ 防 AI 写代码犯错. 这一轴是唯一支持"做点什么"的。⭐ 死链的伤害形式是:AI 读到 console.warn 里的指路,跟过去,发现文件不存在,然后自己编一个替代。本次两条正是这个形状(都指向已删除的 MIGRATION_GUIDE.md)。但规模是 2,而且 C 能以近乎零噪声拿到同样的信号 —— 裸 URL 是没有任何 TypeScript 构造会模仿的明确形状,不像 [x](y)

④ 创业阶段不扩散需求. A 零成本。C 是一个小而明确的检查器,⚠️ 但仍是新增能力,要有人维护、要进 CI、要进 REQUIRED_CONTEXTS 的决定。B 明显超出这个阶段该花的力气 —— 194 : 2 的信噪比不是一个创业期项目该买的单。

PM 推荐:A,并把 C 作为"若确实想要这个能力"时唯一值得计价的形状

理由压在 ①④ 上:实测债务已清零,积累速率可忽略,而卡片自己的分叉规则就写着"数量小则手修"。⛔ B 是分诊设想的形状,也正是测量排除掉的那一个 —— 它以 194 : 2 的比例买信号,而它自带的误报防护恰好挡不住本次的缺陷形态。

⚠️ 若选 C,连带项要先说清:它是新增闸门,需要决定是否进 REQUIRED_CONTEXTS(本轮 #6316 刚做过一次同类判断),以及 .md/.mdx 里那 116 条裸 URL 为零的事实是否意味着两个 population 应当合并检查还是永远分开。

⛔ 推荐是输入,不是放行。

What is not blocked by this

PR #6428 (the two hand repairs) is independent and correct under all three options — the dead pointers are wrong regardless of whether a gate ever learns to see them. It is reviewed and armed separately.

Refs: #6342 (the card whose implementation produced this) · PR #6428 · #6275 / PR #6339 (the worked example the card was built on) · #6280 (the adjacent stale-surface-documentation card, landed)


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions