Repository navigation
Commit f6caa12
fix(scripts): the where-matcher lift reads identifiers from code, never from template-literal text (#30472)
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wgMPwCdpvbf2imf5vac9Zoo4)_
domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF
Fixes #29860
Clause-②: no — an internal instrument; no product surface moves
Metadata-protocol: none
## 维护者速读
- **改了什么:** where-matcher
一致性检查在"抽出测试替身的过滤函数单独运行"时,改为只顺着代码里出现的名字去找同文件的依赖,字符串、模板文字的正文和注释里的单词不再算数;`${…}`
里的表达式仍算代码照收。
- **为什么改:** 替身的报错文案里写了 "sparse driver",检查就把旁边的 `driver` 对象一起拉进来,运行时报
`name is not defined`,一个本来合规的替身被判"无法判定",挡住了 PR
#29858,作者只好改文案绕过去。门禁结论不该取决于报错文案用了哪个英文单词。
- **风险与回滚:** 只动一个仓库内部检查脚本,不发布任何包。全树 684 个过滤函数改前改后判定逐条一致,耗时持平(约 15
秒)。回滚即撤 PR。
- **先看:** `scripts/check-where-matcher-conformance.mjs` 的
`identifiersIn`(改为遍历语法树)与 `buildCallable` 里读 `sourceIdentifiers`
的三行;self-test 新电池 `#29860`。
- **两分钟验证:** `pnpm check:where-matcher`,预期 self-test 打印 OK,全树一行 `0
silently-wrong and 0 unjudged`(合 main 后共 685 个 matcher)。
- **需要你做的:** 无,席位落地。
## What changes
`identifiersIn` was a word regex over source TEXT
(`/\b([A-Za-z_$][A-Za-z0-9_$]*)\b/g`), so every word in a string
literal, a template literal's text, a regular expression or a comment
counted as a name the lift should follow. It now walks the parsed tree
and collects `Identifier` nodes only: a `${…}` hole is code and is
collected, the text around it is not. Discovery computes the sets off
the nodes it already holds (the candidate's `sourceIdentifiers`, and
each visible declaration's `identifiers` beside its `text`), so nothing
is re-parsed and no fragment goes through a second parse door.
`buildCallable` follows those sets instead of re-scanning text. The
header's "Extraction" paragraph says what "names" now means.
Over-inclusion stays in one direction only, as before: a property name
(`row.name`) is still an identifier node, and a name that resolves to no
same-file declaration is skipped by the lift.
**Premise note.** The card says ordinary string literals already behaved
this way. Measured on `main`, they did not: the same regex read them
too. This PR covers both spellings, and the self-test pins both.
## Tests
New self-test battery `#29860: the lift reads identifiers from code,
never from text` (floor 7; roster floor 4 → 5):
- `FIXTURE_TEXT_NAMES_SIBLING`, the card's shape: a refusing matcher
inside a factory whose messages say "sparse driver" (one template
literal with a `${k}` hole, one plain string), beside `const driver = {
name, … }` that closes over the factory parameter. Pinned: discovered;
`driver` and `implemented` not collected; lifts and judges CONFORMING
(refusing).
- `FIXTURE_HOLE_NAMES_HELPER`, the other direction: a same-file helper
`label` named only inside a `${…}` hole on the matcher's answering path.
Pinned: `label` collected; the matcher lifts with it and judges
CONFORMING.
<details><summary>Mutation replay (one-off, restored by blob hash ==
HEAD)</summary>
- Old semantics (word regex over the node's text): self-test exit 1 —
`template-literal TEXT names no identifier: "driver" in the message is
not collected`, `a matcher beside text naming a sibling binding lifts
and is CONFORMING, not UNJUDGED`.
- Holes skipped (`if (ts.isTemplateExpression(n)) return;`): self-test
exit 1 — `the helper named only inside the hole is collected`, `so the
hole-reading matcher lifts with its helper and is CONFORMING`.
</details>
<details><summary>Real producer replay</summary>
`packages/objectql/src/write-answer-declared-columns.test.ts` read in
memory with its messages put back to `sparse driver:` (the wording PR
#29858 had to rename away), then `discoverInSource` + `judge`:
- `main` (989ae42): `46 matches UNJUDGED could not lift:
ReferenceError: name is not defined`
- this branch: `46 matches CONFORMING`
</details>
## Acceptance notes
- Whole-tree verdicts, before (989ae42) and after: 692 structural
candidates, 257 CONFORMING, 427 CONFORMING by refusing, 8 OUT_OF_SCOPE,
both runs; a per-candidate diff (file, line, name, verdict, reason) is
empty. No verdict changed, so no matcher newly lifts. Gate line both
runs: `684 matcher(s) discovered … 0 silently-wrong and 0 unjudged`.
Wall time about 15.6 s before, 14.9 s after. After merging `origin/main`
(head da5a909): `685 matcher(s) discovered … 0 silently-wrong and 0
unjudged`.
- `scripts/check-objectql-double-limit.mjs` carries a near-identical
lifter (`identifiersIn` at line 400 is the same word regex). Same defect
class, no real producer measured there; not touched (outside this card's
file surface), reported to the seat.
## Verification
Gate list derived by `node scripts/pm/dispatch-gates.mjs --commands
--repo objectstack-ai/objectstack` (31 commands), each run with its exit
code recorded before any pipe and reconciled with `--ran`; `pnpm lint`
run. Readings are in the os-dev-report on #29860.
No changeset: the diff is one repo-root script that no released package
ships (`skip-changeset`).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Utp6CYZ6tmbWZDWzLW4Yzg)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 0c7e95a commit f6caa12
1 file changed
Lines changed: 103 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
216 | 216 | | |
217 | 217 | | |
218 | 218 | | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
219 | 222 | | |
220 | 223 | | |
221 | 224 | | |
| |||
316 | 319 | | |
317 | 320 | | |
318 | 321 | | |
319 | | - | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
320 | 327 | | |
321 | 328 | | |
322 | 329 | | |
| |||
328 | 335 | | |
329 | 336 | | |
330 | 337 | | |
331 | | - | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
332 | 342 | | |
333 | 343 | | |
334 | 344 | | |
335 | | - | |
| 345 | + | |
336 | 346 | | |
337 | 347 | | |
338 | 348 | | |
339 | 349 | | |
340 | 350 | | |
341 | 351 | | |
342 | | - | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
343 | 368 | | |
344 | | - | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
345 | 374 | | |
346 | | - | |
| 375 | + | |
347 | 376 | | |
348 | 377 | | |
349 | 378 | | |
| |||
474 | 503 | | |
475 | 504 | | |
476 | 505 | | |
| 506 | + | |
477 | 507 | | |
478 | 508 | | |
479 | 509 | | |
| |||
498 | 528 | | |
499 | 529 | | |
500 | 530 | | |
501 | | - | |
| 531 | + | |
502 | 532 | | |
503 | 533 | | |
504 | 534 | | |
505 | 535 | | |
506 | 536 | | |
507 | 537 | | |
508 | | - | |
509 | | - | |
| 538 | + | |
| 539 | + | |
510 | 540 | | |
511 | 541 | | |
512 | 542 | | |
| |||
649 | 679 | | |
650 | 680 | | |
651 | 681 | | |
652 | | - | |
| 682 | + | |
653 | 683 | | |
654 | 684 | | |
655 | 685 | | |
| |||
844 | 874 | | |
845 | 875 | | |
846 | 876 | | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
847 | 910 | | |
848 | 911 | | |
849 | 912 | | |
| |||
876 | 939 | | |
877 | 940 | | |
878 | 941 | | |
| 942 | + | |
879 | 943 | | |
880 | 944 | | |
881 | 945 | | |
882 | 946 | | |
883 | | - | |
| 947 | + | |
884 | 948 | | |
885 | 949 | | |
886 | 950 | | |
| |||
991 | 1055 | | |
992 | 1056 | | |
993 | 1057 | | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
994 | 1085 | | |
995 | 1086 | | |
996 | 1087 | | |
| |||
1110 | 1201 | | |
1111 | 1202 | | |
1112 | 1203 | | |
| 1204 | + | |
1113 | 1205 | | |
1114 | 1206 | | |
1115 | 1207 | | |
| |||
0 commit comments