Skip to content

platform-checklist reuses the shared resolver's RULE but is still not a registered corpus — the anchor grammar stays forked, and the two copies have already drifted (23 extensions vs 8) #18107

Description

@claude

Follow-up to #16898 (PR #18100), filed by the domain:devx PM seat as the registration gap that review explicitly ruled out of #16898's scope. ⭐ The anchor for this card is a sentence the tree itself now carries, and the reason it is a card rather than an edit is that narrowing a quoted ruling is the maintainer's act, not a gate author's.

The sentence this card is anchored on

scripts/symbol-anchors.mjs reproduces the 2026-09-01 ruling (总监批 #27, on #13556) in its header, and states two consequences as load-bearing. The second reads, verbatim:

One resolver. #13788 (1,647 platform-checklist source citations) was ruled the same shape and is serial behind #13556. It reuses THIS module by registering a corpus. ⛔ Do not fork this file for a second corpus; if a corpus needs behaviour this core lacks, widen the core.

And the paragraph below it says why, mechanically:

Two copies of that rule drift, and they drift SILENTLY: each gate stays green on its own corpus while meaning something different by "resolves". A second corpus is therefore a registration, and the resolution rule has exactly one implementation and one self-test.

⇒ That sentence was false before PR #18100 (the checklist reused nothing) and is half-true after it: the rule is now shared, the corpus is still not registered, and the grammar is still a second implementation.

Measured — origin/main @ 3aaea38794 vs PR #18100 head

grep -c in scripts/check-platform-checklist.mjs. Nonsense control (defineCorpusZZZ) reads 0 on the same file, so the zeros below are readings, not a broken probe.

symbol on main on #18100 head
symbolResolutionClass 0 10 ✅ the rule is shared — this is what #16898 bought
defineCorpus 0 0 ⬅ the gap
sweepCorpus 0 0 ⬅ the gap
extractAnchors (shared detector) 0 0 ⬅ the gap
ANCHORABLE_EXTENSIONS (local redefinition) 4
SYMBOL_ANCHOR (local regex) 6
findSymbolAnchors (local detector) 3

For scale: defineCorpus has 3 call sites in the tree — scripts/check-adr-symbol-anchors.mjs#CORPUS, scripts/check-scripts-symbol-anchors.mjs#CORPUS, scripts/check-system-context-census.mjs#CORPUS. Rule-only reusers that register nothing: scripts/isystem-census.mjs (defineCorpus count 0) and, after #18100, the platform checklist. ⇒ 3 registered, 2 not.

⭐ The drift the ruling predicted is already measurable, not hypothetical

Two modules, one importing the other, both define a constant named ANCHORABLE_EXTENSIONS, with different contents:

  • shared scripts/symbol-anchors.mjs#ANCHORABLE_EXTENSIONS23 extensions (ts tsx mts cts js jsx mjs cjs sh yaml yml json jsonc md mdx sql css scss py rs go toml prisma)
  • local, in scripts/check-platform-checklist.mjs8 (ts tsx mts cts js mjs cjs json)

The local set is a strict subset: 15 extensions the shared corpora treat as anchorable are missing. And the checklist does not skip an anchor outside its set — it reds on it:

UNRESOLVABLE ANCHOR — …: this gate reads symbols out of ts/tsx/mts/cts/js/mjs/cjs/json only …

The same anchor spelling is a resolved anchor in one governed corpus and a hard error in another. RUNNER.md#someHeading, a .sh#fn, a .yaml#key — legal and resolved under the registered corpora, refused here. That is precisely "each gate … meaning something different by resolves", and this corpus's own population is .md and .json, so .md anchors are not a theoretical shape in it.

A second divergence in the detector itself: shared scripts/symbol-anchors.mjs#extractAnchors skips code fences (except a comment header naming a repo path) and honours <!-- anchor-exempt: … --> markers. The local findSymbolAnchors is a bare matchAll over the whole file — no fence handling, no exemption markers. An anchor-shaped string quoted inside a fence in RUNNER.md is judged here and skipped there.

⚠️ What this card is NOT asking for

Not "widen the shared resolver until this corpus goes green." #18100's own error text forbids that, correctly:

⛔ Do not widen scripts/symbol-anchors.mjs to make this green: it is shared with four other corpora.

That instruction is about the resolution rule — refusing to loosen what counts as a symbol being present in order to clear a red. This card is about registration and the detector, a different surface. Both sentences can be true at once, and the card should say so in its PR rather than let the next reader collide them.

The concrete obstacle — and it is the ruling's own escape hatch

Registration is not a rename; scripts/symbol-anchors.mjs#defineCorpus cannot express this corpus as it stands:

  • it requires a non-empty docRoots and filters by docPattern, a regex tested against the basename only, defaulting to /\.mdx?$/. This corpus is .md and .json — expressible (/\.(md|json)$/), fine.
  • but its walker recurses every subdirectory, and this corpus deliberately excludes runs/ ("run records are outputs"). There is no way to say that through docRoots/docPattern.
  • docProjection exists for non-prose sources, which is the right seam for the .json half.

⇒ Exactly the case the ruling names: "if a corpus needs behaviour this core lacks, widen the core." Today no card owns that widening#13788, which was the card that was supposed to register this corpus, closed completed on 2026-09-04 having built its own resolver instead, and #16898 un-forked only the rule.

What this card owes

  1. A root-exclusion (or equivalent) on scripts/symbol-anchors.mjs#defineCorpus, with its own two-direction self-test — a fixture whose excluded subtree is not swept and a control proving the same sweeper still reaches an included one.
  2. scripts/check-platform-checklist.mjs registered through defineCorpus/sweepCorpus, its local SYMBOL_ANCHOR, ANCHORABLE_EXTENSIONS and findSymbolAnchors deleted rather than left beside the shared ones.
  3. A pin that the extension vocabulary has one definition — the drift above is only invisible because nothing asserts the two sets are the same object.
  4. ⚠️ The migration will change verdicts (15 extensions become anchorable here, fences stop being scanned). ⛔ Do not absorb that into the residual ledger silently: measure the delta and state it, and if it grows the residual, say so in the PR — Drain the 47 bad-citation rows on SHARED_RESOLVER_RESIDUAL — a closed ledger with no owner is how it turns back into an allow-list #18104 already owns draining that ledger, and a registration that quietly refills it would undo that card.

⚠️ Known context the implementer needs up front

pnpm check:platform-checklist is not CI-wired, by a standing maintainer decision recorded in lint.yml; the visibility gap is carded separately as #11730. ⇒ A red from this gate reaches whoever runs it, ⛔ not every PR. State that plainly rather than implying reach the check does not have. ⛔ Do not touch the CI wiring here.

Provenance

Ruled by this seat while reviewing PR #18100 (ruling comment 5658212282, Q1 → A: the rule-level binding is in scope, the registration gap is its own card). Duplicate search: all 491 open issues walked by repo-scoped REST pagination (⛔ the search endpoint is refused by this container's proxy) and grepped for defineCorpus / registering a corpus / symbol-anchors / sweepCorpus / registration — no existing registration-gap card. Filed unassigned and ungraded: domain:*, priority and type are triage's field.


决策箱卡面块(domain:devx 派发席补,2026-09-17T07:2xZ · ⛔ 不改上方立卡席原文)

维护者速读:PR #18588(绿、draft、头 3683a4b9e,2026-09-17T06:2xZ 读)把 platform-checklist 注册成共享语料,卡面要求的全做到了;顺带让一条 UNRESOLVABLE ANCHOR 硬红永远不再响(grep -c:main = 1,PR 头 = 0)。今日实测命中 0。SKILL.md:390 把「门禁削弱(删必查)」列在人工地板 ⇒ ⛔ 派发席不代裁。请裁 A / B / C,本席建议 A。完整选项代价表、四轴论证与裁后执行段在评论 5709893125

os-decision-facets
① 项目长远合理性:A 缩小特例(删一份分叉文法,五个语料同一套规则),B 扩大契约增生(第四个共享开关),C 恢复特例。
② 实际业务拉动:今天 0 —— 无人撞上;拉动只在未来作者写错扩展名、而没有任何东西告诉他的那一刻。
③ 防 AI 犯错:A 把响亮拒绝换成静默容忍(单棱反向),B 保住响亮拒绝;故 A 的补偿控制必须是一张卡,不是一句注释。
④ 创业阶段不扩散:A = remove;B = declare-and-maintain,默认 off 的开关同样是永久义务。
Prior rulings read: unresolvable,anchorable,extension,silent → 11 hits; ADR-0106 D6, ADR-0029 D9.9, ADR-0056 D8, ADR-0057 D7, ADR-0058 D6, ADR-0062 D3, ADR-0062 D7, ADR-0094 D5, ADR-0105 D5 —— 逐条读过,全部是运行时失败姿态/权限投影面的裁决,⛔ 无一条裁的是门禁检查的去留,故不构成既有裁决。

推荐 A。自检行:只看①选 A;②③④ 是否翻转:否(③ 单棱反向,但其今日拉动为 0,且 A 的补偿控制 = 同轮另立卡)。回退项 B。置信缺口:读不到这条红在过去是否响过 —— 门禁不留痕。

⚠️ 本块原先只落在评论 5709893125 里,而 check-half-states 的 H62 是按卡面 body 逐字 grep 的 ⇒ 机器读作「无四棱块」。⛔ 这是派发席的落卡失误,已在此补正,原评论内容不动。


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions