Summary
merge-batch-graphs.py (understand skill) classifies test nodes purely by path convention — is_test_path() requires a .test. / .spec. basename infix or a tests/ / __tests__/ root. Repos whose verification harness lives elsewhere get every production→test tested_by edge silently dropped during the merge, because the pair is read as production↔production and discarded as semantically broken.
Concrete case
174-file Next.js + Payload CMS repo whose CI verification harness lives in scripts/ (scripts/verify-*.mjs, scripts/smoke.mjs — 8 scripts, no .test./.spec. naming). On a full /understand build:
- The file-analyzers got it right: all eight scripts tagged
test + verification, while scripts/shoot.mjs (a screenshot utility in the same directory) was correctly tagged plain utility. The semantic signal exists and is accurate.
- The merge dropped all 23
tested_by edges targeting those scripts. The scripts genuinely assert (accumulator pattern ending in process.exit(failed ? 1 : 0)) and three of them are hard CI gates.
- Incremental updates do not re-drop restored edges; only a full merge does — so the loss recurs on every
--full rebuild and has to be manually re-applied each time.
Suggested fix
Have the linker trust the test tag the file-analyzers already emit (union with the path heuristic, rather than path-only). The path convention stays as the fallback for files the analyzers didn't tag; the tag covers the naming false-negatives.
— 🤖 Claude, on behalf of @PBNZ
Summary
merge-batch-graphs.py(understand skill) classifies test nodes purely by path convention —is_test_path()requires a.test./.spec.basename infix or atests//__tests__/root. Repos whose verification harness lives elsewhere get every production→testtested_byedge silently dropped during the merge, because the pair is read as production↔production and discarded as semantically broken.Concrete case
174-file Next.js + Payload CMS repo whose CI verification harness lives in
scripts/(scripts/verify-*.mjs,scripts/smoke.mjs— 8 scripts, no.test./.spec.naming). On a full/understandbuild:test+verification, whilescripts/shoot.mjs(a screenshot utility in the same directory) was correctly tagged plainutility. The semantic signal exists and is accurate.tested_byedges targeting those scripts. The scripts genuinely assert (accumulator pattern ending inprocess.exit(failed ? 1 : 0)) and three of them are hard CI gates.--fullrebuild and has to be manually re-applied each time.Suggested fix
Have the linker trust the
testtag the file-analyzers already emit (union with the path heuristic, rather than path-only). The path convention stays as the fallback for files the analyzers didn't tag; the tag covers the naming false-negatives.— 🤖 Claude, on behalf of @PBNZ